     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.0.19
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.11 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 02/06/2022 ] ; 2022 modification (previous: 29/04/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
    24                                  ; 04/02/2016 (v0.2.0.17) - 29/04/2022 (v0.2.0.18) - 09/05/2022 (v0.2.0.19)
    25                                  ; Assembler: NASM 2.15
    26                                  ;	nasm unix386.s -l unix386.lst -o unix386 -Z error.txt
    27                                  
    28                                  ; 24/12/2013
    29                                  
    30                                  ; Entering protected mode:
    31                                  ; Derived from 'simple_asm.txt' source code file and 
    32                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    33                                  ; (gregor.brunmar@home.se)
    34                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    35                                  ;
    36                                  
    37                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    38                                  ; by Michael Chourdakis (2009) 
    39                                  ; http://www.codeproject.com/Articles/45788/
    40                                  ; http://www.michaelchourdakis.com
    41                                  ;
    42                                  
    43                                  ; Global Descriptor Table:
    44                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    45                                  ; by Linus Torvalds (1991-1992)
    46                                  ;
    47                                  
    48                                  KLOAD	equ 10000h ; Kernel loading address
    49                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    50                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    51                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    52                                  ; 19/03/2015
    53                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    54                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    55                                  ; 24/03/2015
    56                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    57                                  ; 19/03/2015
    58                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    59                                  		     ; (at the end of the 1st 4MB)
    60                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    61                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    62                                  
    63                                  ; 27/12/2013
    64                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    65                                  
    66                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    67                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    68                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    69                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    70                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    71                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    72                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    73                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    74                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    75                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    76                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    77                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    78                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    79                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    80                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    81                                  ;----------------------------------------
    82                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    83                                  ;-----------------------------------------------------------------------------
    84                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    85                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    86                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    87                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    88                                  
    89                                  ; Memory Allocation Table Address
    90                                  ; 05/11/2014
    91                                  ; 31/10/2014
    92                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    93                                  					; the 1st 1 MB memory space.
    94                                  					; (This address must be aligned
    95                                  					;  on 128 KB boundary, if it will be
    96                                  					;  changed later.)
    97                                  					; ((lower 17 bits of 32 bit M.A.T.
    98                                  					;   address must be ZERO)).
    99                                  					; ((((Reason: 32 bit allocation 
   100                                  					;     instructions, dword steps)))
   101                                  					; (((byte >> 12 --> page >> 5)))  
   102                                  ;04/11/2014	
   103                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   104                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   105                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   106                                  ;
   107                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   108                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   109                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   110                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   111                                  
   112                                  ; 17/02/2015 (unix386.s)
   113                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   114                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   115                                  ;
   116                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   117                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   118                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   119                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   120                                  
   121                                  
   122                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   123                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   124                                  ;
   125                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   126                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   127                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   128                                  		      ; otherwise it is standard FDPT with physical values 	
   129                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   130                                  		      ; (obsolete for IDE/ATA drives)
   131                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   132                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   133                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   134                                  			; Bit 4 : Reserved. Always 0
   135                                  			; Bit 3 : Set to 1 if more than 8 heads
   136                                  			; Bit 2-0 : Reserved. Alsways 0
   137                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   138                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   139                                  
   140                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   141                                  ; (11 bytes long) will be used by diskette handler/bios
   142                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   143                                  
   144                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   145                                  
   146                                  [ORG 0] 
   147                                  	; 12/11/2014
   148                                  	; Save boot drive number (that is default root drive)
   149 00000000 8816[8A66]              	mov	[boot_drv], dl ; physical drv number
   150                                  
   151                                  	; Determine installed memory
   152                                  	; 31/10/2014
   153                                  	;
   154 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   155 00000007 CD15                    	int	15h	   ; for large configurations
   156 00000009 7308                    	jnc	short chk_ms
   157 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   158 0000000D CD15                    	int	15h
   159                                  	;	   
   160                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   161                                  	;out	70h, al ; select CMOS register
   162                                  	;in	al, 71h ; read data (1 byte)
   163                                  	;mov	cl, al
   164                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   165                                  	;out	70h, al ; select CMOS register
   166                                  	;in	al, 71h ; read data (1 byte)
   167                                  	;mov	ch, al
   168                                   	;      
   169 0000000F 89C1                    	mov	cx, ax
   170 00000011 31D2                    	xor	dx, dx
   171                                  chk_ms:
   172 00000013 890E[1E69]              	mov	[mem_1m_1k], cx
   173 00000017 8916[2069]              	mov	[mem_16m_64k], dx
   174                                  	; 05/11/2014
   175                                  	;and	dx, dx
   176                                  	;jz	short L2
   177 0000001B 81F90004                        cmp     cx, 1024
   178 0000001F 7351                    	jnb	short L0
   179                                  		 ; insufficient memory_error	
   180                                  		 ; Minimum 2 MB memory is needed... 
   181                                  	; 05/11/2014
   182                                  	; (real mode error printing)
   183 00000021 FB                      	sti
   184 00000022 BE[3600]                	mov	si, msg_out_of_memory
   185 00000025 BB0700                  	mov	bx, 7
   186 00000028 B40E                    	mov	ah, 0Eh	; write tty
   187                                  oom_1:
   188 0000002A AC                      	lodsb
   189 0000002B 08C0                    	or	al, al
   190 0000002D 7404                    	jz	short oom_2
   191 0000002F CD10                    	int	10h
   192 00000031 EBF7                    	jmp	short oom_1
   193                                  oom_2:
   194 00000033 F4                              hlt
   195 00000034 EBFD                    	jmp	short oom_2
   196                                  
   197                                  ; 04/02/2022
   198                                  ; 05/11/2014
   199                                  msg_out_of_memory:
   200 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   201 00000039 496E73756666696369-             db      'Insufficient memory !'
   201 00000042 656E74206D656D6F72-
   201 0000004B 792021             
   202 0000004E 0D0A                    	db	0Dh, 0Ah
   203                                  _int13h_48h_buffer: 
   204                                  	; 04/02/2022 (Runix Kernel v0.2.0.18, 'diskinit.inc')
   205 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   205 00000059 324D42206D656D6F72-
   205 00000062 79206973206E656564-
   205 0000006B 65642E29           
   206 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   207                                  
   208                                  L0:
   209                                  %include 'diskinit.inc' ; 07/03/2015
   210                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - DISKINIT.INC
   211                              <1> ; Last Modification: 09/05/2022
   212                              <1> 
   213                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   214                              <1> 
   215                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   216                              <1> 
   217                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Runix Kernel v0.2.0.18)
   218                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   219                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   220                              <1> ;L0:
   221                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   222                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   223 00000072 BA7F00              <1> 	mov	dx, 7Fh
   224                              <1> L1:	
   225 00000075 FEC2                <1> 	inc	dl
   226 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   227                              <1> 			; Phoenix EDD v1.1 - EDD v3
   228 00000079 BBAA55              <1> 	mov	bx, 55AAh
   229 0000007C CD13                <1> 	int 	13h
   230 0000007E 721A                <1> 	jc	short L2
   231                              <1> 
   232 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   233 00000084 7514                <1> 	jne	short L2
   234 00000086 FE06[8D66]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   235 0000008A 8816[8C66]          <1>         mov     [last_drv], dl  ; last hard disk number
   236 0000008E BB[1066]            <1> 	mov	bx, hd0_type - 80h
   237 00000091 01D3                <1> 	add	bx, dx	 
   238 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   239                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   240                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   241                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   242                              <1>                          ;            (EDD) ready (DPTE ready)
   243                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   244                              <1>                          ;            (EDD-3)
   245                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   246 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   247 00000098 72DB                <1> 	jb	short L1
   248                              <1> L2:
   249                              <1> 	; 23/11/2014
   250                              <1> 	; 19/11/2014
   251 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   252                              <1> 	; 04/02/2016 (esi -> si)
   253 0000009C BE[8E66]            <1> 	mov	si, fd0_type
   254                              <1> L3:
   255                              <1> 	; 14/01/2015
   256 0000009F 8816[8B66]          <1> 	mov	[drv], dl
   257                              <1> 	;
   258 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   259 000000A5 CD13                <1> 	int	13h	
   260 000000A7 7210                <1> 	jc	short L4
   261                              <1> 		; BL = drive type (for floppy drives)
   262                              <1> 		; DL = number of floppy drives
   263                              <1> 		;		
   264                              <1> 		; ES:DI = Address of DPT from BIOS
   265                              <1> 		;
   266 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   267                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   268                              <1> 	; 14/01/2015
   269 000000AB E8BB01              <1> 	call	set_disk_parms
   270                              <1> 	; 10/12/2014
   271 000000AE 81FE[8E66]          <1> 	cmp	si, fd0_type
   272 000000B2 7705                <1> 	ja	short L4
   273 000000B4 46                  <1> 	inc	si ; fd1_type
   274 000000B5 B201                <1> 	mov	dl, 1
   275 000000B7 EBE6                <1> 	jmp	short L3
   276                              <1> L4:
   277                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   278 000000B9 B27F                <1> 	mov	dl, 7Fh
   279                              <1> 	; 24/12/2014 (Temporary)
   280 000000BB 803E[8D66]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   281                              <1> 	;ja	L10       ; yes, all fixed disk operations
   282                              <1> 			  ; will be performed according to
   283                              <1> 			  ; present EDD specification
   284                              <1> 	; 02/01/2022
   285 000000C0 7603                <1> 	jna	short L5
   286 000000C2 E99100              <1> 	jmp	L10
   287                              <1> L5:
   288 000000C5 FEC2                <1> 	inc 	dl
   289 000000C7 8816[8B66]          <1>         mov     [drv], dl
   290 000000CB 8816[8C66]          <1>         mov     [last_drv], dl ; 14/01/2015
   291 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   292 000000D1 CD13                <1> 	int	13h	; (conventional function)
   293                              <1> 	;jc	L13	; fixed disk drive not ready
   294                              <1> 	; 02/01/2022
   295 000000D3 7303                <1> 	jnc	short L6
   296 000000D5 E98301              <1> 	jmp	L13
   297                              <1> L6:
   298 000000D8 8816[8D66]          <1>         mov     [hdc], dl ; number of drives
   299                              <1> 	;; 14/01/2013
   300                              <1> 	;;push	cx
   301 000000DC E88A01              <1> 	call	set_disk_parms
   302                              <1> 	;;pop	cx
   303                              <1> 	;
   304                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   305 000000DF 8A16[8B66]          <1>         mov     dl, [drv]
   306 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   307 000000E6 80FA80              <1> 	cmp	dl, 80h
   308 000000E9 7603                <1> 	jna	short L7
   309 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   310                              <1> L7:	
   311 000000EE 31C0                <1> 	xor	ax, ax
   312 000000F0 8ED8                <1> 	mov	ds, ax
   313 000000F2 8B37                <1>         mov     si, [bx]
   314 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   315 000000F7 8ED8                <1> 	mov	ds, ax
   316 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   317                              <1> 	;jne	L12 ; invalid FDPT
   318                              <1> 	; 02/01/2022
   319 000000FC 7403                <1> 	je	short L7_8
   320 000000FE E95601              <1> 	jmp	L12
   321                              <1> L7_8:
   322 00000101 BF0000              <1> 	mov	di, HD0_DPT
   323 00000104 80FA80              <1> 	cmp	dl, 80h
   324 00000107 7603                <1> 	jna	short L8
   325 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   326                              <1> L8:
   327                              <1> 	; 30/12/2014
   328 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   329 0000010F 8EC0                <1> 	mov	es, ax
   330                              <1> 	; 24/12/2014
   331 00000111 B90800              <1> 	mov	cx, 8
   332 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   333 00000116 8CC8                <1> 	mov	ax, cs
   334 00000118 8ED8                <1> 	mov	ds, ax
   335                              <1> 	; 02/02/2015
   336 0000011A 8A0E[8B66]          <1>         mov     cl, [drv]
   337 0000011E 88CB                <1> 	mov	bl, cl
   338 00000120 B8F001              <1> 	mov	ax, 1F0h
   339 00000123 80E301              <1> 	and	bl, 1
   340 00000126 7406                <1> 	jz	short L9
   341 00000128 C0E304              <1> 	shl	bl, 4
   342 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   343                              <1> L9:
   344 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   345 0000012F 050602              <1> 	add	ax, 206h
   346 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   347 00000133 88D8                <1> 	mov	al, bl
   348 00000135 04A0                <1> 	add	al, 0A0h
   349 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   350                              <1> 	;
   351 00000138 FE06[8B66]          <1> 	inc	byte [drv]
   352 0000013C BB[1066]            <1> 	mov	bx, hd0_type - 80h
   353 0000013F 01CB                <1> 	add	bx, cx
   354 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   355 00000144 A0[8D66]            <1> 	mov	al, [hdc]
   356 00000147 FEC8                <1> 	dec	al
   357                              <1> 	;jz	L13
   358                              <1> 	; 02/01/2022
   359 00000149 7408                <1> 	jz	short L9_10
   360 0000014B 80FA80              <1> 	cmp	dl, 80h
   361                              <1>         ;jna	L5
   362                              <1> 	;jmp	L13
   363                              <1> 	; 02/01/2022
   364 0000014E 7703                <1> 	ja	short L9_10
   365 00000150 E972FF              <1> 	jmp	L5
   366                              <1> L9_10:
   367 00000153 E90501              <1>         jmp     L13
   368                              <1> L10:
   369 00000156 FEC2                <1> 	inc 	dl
   370                              <1> 	; 25/12/2014
   371 00000158 8816[8B66]          <1> 	mov	[drv], dl
   372 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   373 0000015E CD13                <1> 	int	13h	; (conventional function)
   374                              <1> 	;jc	L13
   375                              <1> 	; 02/01/2022
   376 00000160 72F1                <1> 	jc	short L9_10
   377                              <1> 	; 14/01/2015
   378 00000162 8A16[8B66]          <1> 	mov	dl, [drv]
   379 00000166 52                  <1> 	push	dx
   380 00000167 51                  <1> 	push	cx
   381 00000168 E8FE00              <1> 	call	set_disk_parms
   382 0000016B 59                  <1> 	pop	cx
   383 0000016C 5A                  <1> 	pop	dx
   384                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   385                              <1> 	; 04/02/2016 (esi -> si)
   386                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   387                              <1> 	;		 ; at the '_end' of kernel.
   388                              <1> 	;mov	word [si], 30
   389                              <1> 	; 06/07/2016
   390 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   391                              <1> 	; 09/07/2016
   392 00000170 B81E00              <1> 	mov	ax, 001Eh
   393 00000173 8824                <1> 	mov	[si], ah ; 0
   394 00000175 46                  <1> 	inc	si
   395 00000176 8904                <1> 	mov	word [si], ax
   396                              <1>  	; word [si] = 30
   397                              <1> 	;
   398 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   399 0000017A CD13                <1> 	int	13h
   400                              <1>         ;jc	L13
   401                              <1> 	; 02/01/2022
   402 0000017C 72D5                <1> 	jc	short L9_10
   403                              <1> 	; 04/02/2016 (ebx -> bx)
   404                              <1> 	; 14/01/2015
   405                              <1> 	;sub	bx, bx
   406 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   407 00000180 88D3                <1> 	mov	bl, dl
   408 00000182 80EB80              <1> 	sub	bl, 80h
   409 00000185 81C3[9066]          <1> 	add	bx, hd0_type
   410 00000189 8A07                <1> 	mov 	al, [bx]
   411 0000018B 0C80                <1> 	or	al, 80h
   412 0000018D 8807                <1> 	mov 	[bx], al	
   413 0000018F 81EB[8E66]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   414 00000193 81C3[DA66]          <1> 	add	bx, drv.status
   415 00000197 8807                <1> 	mov	[bx], al
   416                              <1> 	; 04/02/2016 (eax -> ax)
   417 00000199 8B4410              <1> 	mov	ax, [si+16]
   418 0000019C 854412              <1> 	test	ax, [si+18]
   419 0000019F 7413                <1> 	jz	short L10_A0h 
   420                              <1> 			; 'CHS only' disks on EDD system 
   421                              <1> 			;  are reported with ZERO disk size
   422 000001A1 81EB[DA66]          <1> 	sub	bx, drv.status
   423 000001A5 C1E302              <1> 	shl	bx, 2
   424 000001A8 81C3[BE66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   425 000001AC 8907                <1> 	mov	[bx], ax
   426 000001AE 8B4412              <1> 	mov	ax, [si+18]
   427                              <1> 	;mov	[bx], ax
   428                              <1> 	; 02/01/2022 (BugFix)
   429 000001B1 894702              <1> 	mov	[bx+2], ax
   430                              <1> 
   431                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   432                              <1> 	 ; for CHS disks (28/02/2015)
   433                              <1> 	; 30/12/2014
   434 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   435 000001B7 88D0                <1> 	mov	al, dl
   436 000001B9 83E003              <1> 	and 	ax, 3
   437 000001BC C0E005              <1> 	shl	al, 5 ; *32
   438 000001BF 01C7                <1> 	add 	di, ax
   439 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   440 000001C4 8EC0                <1> 	mov	es, ax
   441                              <1> 	;
   442 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   443 000001C8 88CC                <1> 	mov	ah, cl	
   444 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   445 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   446 000001CE AB                  <1> 	stosw		
   447 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   448 000001D1 FEC0                <1> 	inc	al
   449 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   450 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   451 000001D6 AA                  <1> 	stosb
   452 000001D7 8A440C              <1> 	mov	al, [si+12]
   453 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   454 000001DB 31C0                <1>  	xor	ax, ax
   455                              <1> 	;dec	ax	 ; 02/01/2015 
   456 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   457                              <1> 	;xor	al, al	 ; 02/01/2015	
   458 000001DE AA                  <1> 	stosb		 ; reserved
   459 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   460                              <1> 		         ; (do not disable retries, 
   461                              <1> 			 ; more than 8 heads)
   462 000001E1 AA                  <1> 	stosb
   463 000001E2 8B4404              <1> 	mov	ax, [si+4]
   464 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   465                              <1> 	;push	ax	 ; 02/01/2015
   466 000001E6 8A4408              <1> 	mov	al, [si+8]
   467 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   468 000001EA 29C0                <1> 	sub 	ax, ax
   469                              <1> 	;pop	ax	 ; 02/01/2015	
   470 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   471 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   472 000001EF 243F                <1> 	and 	al, 3Fh	
   473 000001F1 AA                  <1> 	stosb
   474                              <1> 	;sub	al, al	 ; checksum
   475                              <1> 	;stosb
   476                              <1> 	;
   477 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   478 000001F5 AD                  <1> 	lodsw
   479 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   480 000001F7 AD                  <1> 	lodsw
   481 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   482                              <1> 	;
   483                              <1> 	; checksum calculation
   484 000001F9 89FE                <1> 	mov	si, di
   485 000001FB 06                  <1> 	push	es
   486 000001FC 1F                  <1> 	pop	ds
   487                              <1> 	;mov	cx, 16
   488 000001FD B90F00              <1> 	mov 	cx, 15
   489 00000200 29CE                <1> 	sub	si, cx
   490 00000202 30E4                <1> 	xor	ah, ah
   491                              <1> 	;del	cl
   492                              <1> L11:		
   493 00000204 AC                  <1> 	lodsb
   494 00000205 00C4                <1> 	add	ah, al
   495 00000207 E2FB                <1> 	loop	L11
   496                              <1> 	;
   497 00000209 88E0                <1> 	mov	al, ah
   498 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   499 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   500                              <1> 	;
   501 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   502 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   503                              <1> 	;
   504                              <1> 	; 23/02/2015
   505 00000210 57                  <1> 	push	di
   506                              <1> 	; ES:DI points to DPTE (FDPTE) location
   507                              <1> 	;mov	cx, 8
   508 00000211 B108                <1> 	mov	cl, 8
   509 00000213 F3A5                <1> 	rep	movsw	
   510                              <1> 	;
   511                              <1> 	; 23/02/2015
   512                              <1> 	; (P)ATA drive and LBA validation
   513                              <1> 	; (invalidating SATA drives and setting
   514                              <1> 	; CHS type I/O for old type fixed disks)
   515 00000215 5B                  <1> 	pop	bx
   516 00000216 8CC8                <1> 	mov	ax, cs
   517 00000218 8ED8                <1> 	mov	ds, ax
   518 0000021A 268B07              <1> 	mov	ax, [es:bx]
   519 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   520 00000220 7418                <1> 	je	short L11a
   521 00000222 3D7001              <1> 	cmp	ax, 170h
   522 00000225 7413                <1> 	je	short L11a
   523                              <1> 	; invalidation 
   524                              <1> 	; (because base port address is not 1F0h or 170h)
   525 00000227 30FF                <1> 	xor	bh, bh
   526 00000229 88D3                <1> 	mov	bl, dl
   527 0000022B 80EB80              <1> 	sub	bl, 80h
   528 0000022E C687[9066]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   529 00000233 808F[DC66]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   530 00000238 EB14                <1> 	jmp	short L11b
   531                              <1> L11a:	
   532                              <1> 	; LBA validation
   533 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   534 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   535 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   536                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   537 00000242 28FF                <1> 	sub	bh, bh
   538 00000244 88D3                <1> 	mov	bl, dl
   539 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   540 00000249 80A7[DC66]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   541                              <1> 				; bit 0 = LBA ready bit
   542                              <1> 	; 'diskio' procedure will check this bit !
   543                              <1> L11b:
   544 0000024E 3A16[8C66]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   545 00000252 7307                <1>         jnb     short L13
   546 00000254 E9FFFE              <1>         jmp     L10
   547                              <1> L12:
   548                              <1> 	; Restore data registers
   549 00000257 8CC8                <1> 	mov	ax, cs
   550 00000259 8ED8                <1> 	mov	ds, ax	
   551                              <1> L13:
   552                              <1> 	; 13/12/2014
   553 0000025B 0E                  <1> 	push	cs
   554 0000025C 07                  <1> 	pop	es
   555                              <1> L14:
   556 0000025D B411                <1> 	mov 	ah, 11h
   557 0000025F CD16                <1> 	int 	16h
   558                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   559                              <1> 	; 02/01/2022
   560 00000261 7465                <1> 	jz	short L16
   561 00000263 B010                <1> 	mov	al, 10h
   562 00000265 CD16                <1> 	int 	16h
   563 00000267 EBF4                <1> 	jmp 	short L14
   564                              <1> L15:
   565                              <1> 
   566                              <1> ; //////
   567                              <1> 
   568                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   569                              <1> %if 0
   570                              <1> 	; 24/11/2014
   571                              <1> 	; 19/11/2014
   572                              <1> 	; 14/11/2014
   573                              <1> 	; Temporary code for disk searching code check
   574                              <1> 	;
   575                              <1> 	; This code will show existing (usable) drives and also
   576                              <1> 	; will show EDD interface support status for hard disks		
   577                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   578                              <1> 	; no need to get it again in protected mode...) 
   579                              <1> 	;	
   580                              <1> 	; 13/11/2014
   581                              <1> 	mov	bx, 7
   582                              <1> 	mov	ah, 0Eh
   583                              <1> 	mov	al, [fd0_type]
   584                              <1> 	and	al, al
   585                              <1> 	jz	short L15a
   586                              <1> 	mov	dl, al
   587                              <1> 	mov	al, 'F'
   588                              <1> 	int 	10h
   589                              <1> 	mov	al, 'D'
   590                              <1> 	int 	10h
   591                              <1> 	mov	al, '0'
   592                              <1> 	int 	10h
   593                              <1> 	mov	al, ' '
   594                              <1> 	int	10h
   595                              <1> 	call	L15c
   596                              <1> 	mov	al, ' '
   597                              <1> 	int	10h
   598                              <1> 	;
   599                              <1> 	mov	al, [fd1_type]
   600                              <1> 	and	al, al
   601                              <1> 	jz	short L15a
   602                              <1> 	mov	dl, al
   603                              <1> 	mov	al, 'F'
   604                              <1> 	int 	10h
   605                              <1> 	mov	al, 'D'
   606                              <1> 	int 	10h
   607                              <1> 	mov	al, '1'
   608                              <1> 	int 	10h
   609                              <1> 	mov	al, ' '
   610                              <1> 	int	10h
   611                              <1> 	call	L15c
   612                              <1> 	mov	al, ' '
   613                              <1> 	int	10h
   614                              <1> 	mov	al, ' '
   615                              <1> 	int	10h
   616                              <1> L15a:
   617                              <1> 	mov	al, [hd0_type]
   618                              <1> 	and	al, al
   619                              <1> 	jz	short L15b
   620                              <1> 	mov	dl, al
   621                              <1> 	mov	al, 'H'
   622                              <1> 	int 	10h
   623                              <1> 	mov	al, 'D'
   624                              <1> 	int 	10h
   625                              <1> 	mov	al, '0'
   626                              <1> 	int 	10h
   627                              <1> 	mov	al, ' '
   628                              <1> 	int 	10h
   629                              <1> 	call	L15c
   630                              <1> 	mov	al, ' '
   631                              <1> 	int	10h
   632                              <1> 	;
   633                              <1> 	mov	al, [hd1_type]
   634                              <1> 	and	al, al
   635                              <1> 	jz	short L15b
   636                              <1> 	mov	dl, al
   637                              <1> 	mov	al, 'H'
   638                              <1> 	int 	10h
   639                              <1> 	mov	al, 'D'
   640                              <1> 	int 	10h
   641                              <1> 	mov	al, '1'
   642                              <1> 	int 	10h
   643                              <1> 	mov	al, ' '
   644                              <1> 	int 	10h
   645                              <1> 	call	L15c
   646                              <1> 	mov	al, ' '
   647                              <1> 	int	10h
   648                              <1> 	;
   649                              <1> 	mov	al, [hd2_type]
   650                              <1> 	and	al, al
   651                              <1> 	jz	short L15b
   652                              <1> 	mov	dl, al
   653                              <1> 	mov	al, 'H'
   654                              <1> 	int 	10h
   655                              <1> 	mov	al, 'D'
   656                              <1> 	int 	10h
   657                              <1> 	mov	al, '2'
   658                              <1> 	int 	10h
   659                              <1> 	mov	al, ' '
   660                              <1> 	int 	10h
   661                              <1> 	call	L15c
   662                              <1> 	mov	al, ' '
   663                              <1> 	int	10h
   664                              <1> 	;
   665                              <1> 	mov	al, [hd3_type]
   666                              <1> 	and	al, al
   667                              <1> 	jz	short L15b
   668                              <1> 	mov	dl, al
   669                              <1> 	mov	al, 'H'
   670                              <1> 	int 	10h
   671                              <1> 	mov	al, 'D'
   672                              <1> 	int 	10h
   673                              <1> 	mov	al, '3'
   674                              <1> 	int 	10h
   675                              <1> 	mov	al, ' '
   676                              <1> 	int 	10h
   677                              <1> 	call	L15c
   678                              <1> 	mov	al, ' '
   679                              <1> 	int	10h
   680                              <1> 	;
   681                              <1> L15b:
   682                              <1> 	mov	al, 0Dh
   683                              <1> 	int 	10h	
   684                              <1> 	mov	al, 0Ah
   685                              <1> 	int 	10h
   686                              <1> 	;;xor	ah, ah
   687                              <1> 	;;int 	16h	
   688                              <1> 	;
   689                              <1>         ;jmp	L16  ; jmp short L16
   690                              <1>         ; 02/01/2022
   691                              <1> 	jmp	short L16
   692                              <1> 	;
   693                              <1> L15c:
   694                              <1> 	mov	dh, dl
   695                              <1> 	shr	dh, 4
   696                              <1> 	add	dh, 30h
   697                              <1> 	and	dl, 15
   698                              <1> 	add	dl, 30h
   699                              <1> 	mov	al, dh
   700                              <1> 	int	10h
   701                              <1> 	mov	al, dl
   702                              <1> 	int	10h
   703                              <1> 	retn
   704                              <1> 	;
   705                              <1> 	; end of temporary code for disk searching code check
   706                              <1> 
   707                              <1> %endif
   708                              <1> 
   709                              <1> ; //////
   710                              <1> 
   711                              <1> set_disk_parms:
   712                              <1> 	; 09/05/2022
   713                              <1> 	;	disksize = cylinders*spt*heads (*)
   714                              <1> 	; (fd0&fd1 drv.size is calculated with total cylinders) 
   715                              <1> 	;
   716                              <1> 	; 04/02/2016 (ebx -> bx)
   717                              <1> 	; 10/07/2015
   718                              <1> 	; 14/01/2015
   719                              <1> 	;push	bx
   720 00000269 28FF                <1> 	sub	bh, bh
   721 0000026B 8A1E[8B66]          <1> 	mov	bl, [drv]
   722 0000026F 80FB80              <1> 	cmp	bl, 80h
   723 00000272 7203                <1> 	jb	short sdp0
   724 00000274 80EB7E              <1> 	sub	bl, 7Eh
   725                              <1> sdp0:	
   726 00000277 81C3[DA66]          <1> 	add	bx, drv.status
   727 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   728                              <1> 	;
   729 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   730 00000280 88CC                <1> 	mov	ah, cl ; 
   731 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   732 00000285 81EB[DA66]          <1> 	sub	bx, drv.status
   733 00000289 D0E3                <1> 	shl	bl, 1
   734 0000028B 81C3[9466]          <1> 	add	bx, drv.cylinders
   735 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   736 00000290 8907                <1> 	mov	[bx], ax
   737 00000292 50                  <1> 	push	ax ; ** cylinders
   738 00000293 81EB[9466]          <1> 	sub	bx, drv.cylinders
   739 00000297 81C3[A266]          <1> 	add	bx, drv.heads
   740 0000029B 30E4                <1> 	xor	ah, ah
   741 0000029D 88F0                <1> 	mov	al, dh ; heads
   742 0000029F 40                  <1> 	inc	ax
   743 000002A0 8907                <1> 	mov	[bx], ax
   744 000002A2 81EB[A266]          <1>         sub     bx, drv.heads
   745 000002A6 81C3[B066]          <1>         add     bx, drv.spt
   746 000002AA 30ED                <1> 	xor	ch, ch
   747 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   748 000002AF 890F                <1> 	mov	[bx], cx
   749 000002B1 81EB[B066]          <1>         sub     bx, drv.spt
   750 000002B5 D1E3                <1> 	shl	bx, 1
   751 000002B7 81C3[BE66]          <1> 	add	bx, drv.size ; disk size (in sectors)
   752                              <1> 	; LBA size = cylinders * heads * secpertrack
   753 000002BB F7E1                <1> 	mul	cx 
   754 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   755 000002BF 58                  <1> 	pop	ax ; ** cylinders
   756                              <1> 	; 09/05/2022 (fd0&fd1 drv.size = cyls*spt*heads)
   757                              <1> 	;dec	ax ; 1 cylinder reserved (!?) ; (*)
   758 000002C0 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   759 000002C2 8907                <1> 	mov	[bx], ax
   760 000002C4 895702              <1> 	mov	[bx+2], dx
   761                              <1> 	;
   762                              <1> 	;pop	bx
   763 000002C7 C3                  <1> 	retn
   764                              <1> 
   765                              <1> ;align 2
   766                              <1> 
   767                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   768                              <1> ;heads     :  dw 0, 0, 0, 0, 0, 0
   769                              <1> ;spt       :  dw 0, 0, 0, 0, 0, 0
   770                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   771                              <1> 
   772                              <1> ;last_drv:
   773                              <1> ;	db  0
   774                              <1> ;drv_status:
   775                              <1> ;	db  0,0,0,0,0,0
   776                              <1> ;	db 0
   777                              <1> 
   778                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   779                              <1> 
   780                              <1> L16:
   210                                  
   211                                  	; 10/11/2014
   212 000002C8 FA                           	cli	; Disable interrupts (clear interrupt flag)
   213                                  		; Reset Interrupt MASK Registers (Master&Slave)
   214                                  	;mov	al, 0FFh	; mask off all interrupts
   215                                  	;out	21h, al		; on master PIC (8259)
   216                                  	;jmp 	$+2  ; (delay)
   217                                  	;out	0A1h, al	; on slave PIC (8259)
   218                                  	;
   219                                  	; Disable NMI 
   220 000002C9 B080                    	mov   	al, 80h 
   221 000002CB E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   222                                  	; 23/02/2015
   223 000002CD 90                      	nop			;
   224                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   225                                  				; for preventing unknown state (!?)
   226                                  	;
   227                                   	; 20/08/2014
   228                                  	; Moving the kernel 64 KB back (to physical address 0)
   229                                  	; DS = CS = 1000h
   230                                  	; 05/11/2014
   231 000002CE 31C0                    	xor	ax, ax
   232 000002D0 8EC0                    	mov	es, ax ; ES = 0
   233                                  	;
   234 000002D2 B90040                  	mov	cx, (KEND - KLOAD)/4
   235 000002D5 31F6                    	xor	si, si
   236 000002D7 31FF                    	xor	di, di
   237 000002D9 F366A5                  	rep	movsd
   238                                  	;
   239 000002DC 06                      	push	es ; 0
   240 000002DD 68[E102]                	push	L17
   241 000002E0 CB                      	retf
   242                                  	;
   243                                  L17:
   244                                  	; Turn off the floppy drive motor
   245 000002E1 BAF203                          mov     dx, 3F2h
   246 000002E4 EE                              out     dx, al ; 0 ; 31/12/2013
   247                                  
   248                                  	; Enable access to memory above one megabyte
   249                                  L18:
   250 000002E5 E464                    	in	al, 64h
   251 000002E7 A802                    	test	al, 2
   252 000002E9 75FA                            jnz     short L18
   253 000002EB B0D1                    	mov	al, 0D1h	; Write output port
   254 000002ED E664                    	out	64h, al
   255                                  L19:
   256 000002EF E464                    	in	al, 64h
   257 000002F1 A802                    	test	al, 2
   258 000002F3 75FA                            jnz     short L19
   259 000002F5 B0DF                    	mov	al, 0DFh	; Enable A20 line
   260 000002F7 E660                    	out	60h, al
   261                                  ;L20:
   262                                  	;
   263                                  	; Load global descriptor table register
   264                                  
   265                                          ;mov     ax, cs
   266                                          ;mov     ds, ax
   267                                  
   268 000002F9 2E0F0116[B063]                  lgdt    [cs:gdtd]
   269                                  
   270 000002FF 0F20C0                          mov     eax, cr0
   271                                  	; or 	eax, 1
   272 00000302 40                      	inc     ax
   273 00000303 0F22C0                  	mov     cr0, eax
   274                                  
   275                                  	; Jump to 32 bit code
   276                                  	
   277 00000306 66                      	db 66h 			; Prefix for 32-bit
   278 00000307 EA                      	db 0EAh 		; Opcode for far jump
   279 00000308 [0E030000]              	dd StartPM 		; Offset to start, 32-bit
   280                                  				; (1000h:StartPM = StartPM + 10000h)
   281 0000030C 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   282                                  				; assuming that StartPM resides in code32
   283                                  
   284                                  [BITS 32] 
   285                                  
   286                                  StartPM:
   287                                  	; Kernel Base Address = 0 ; 30/12/2013
   288 0000030E 66B81000                	mov ax, KDATA           ; Save data segment identifier
   289 00000312 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   290 00000314 8EC0                           	mov es, ax              ; Move data segment into ES register
   291 00000316 8EE0                           	mov fs, ax              ; Move data segment into FS register
   292 00000318 8EE8                          	mov gs, ax              ; Move data segment into GS register
   293 0000031A 8ED0                            mov ss, ax              ; Move data segment into SS register
   294 0000031C BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   295                                  
   296                                  clear_bss: ; Clear uninitialized data area
   297                                  	; 11/03/2015
   298 00000321 31C0                    	xor	eax, eax ; 0
   299                                  	;mov	ecx, (bss_end - bss_start)/4
   300                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   301                                  	; 27/02/2022
   302 00000323 B9BB050000              	mov	ecx, BSS_SIZE/4
   303 00000328 BF[30690000]            	mov	edi, bss_start
   304 0000032D F3AB                    	rep	stosd  	
   305                                  
   306                                  memory_init:
   307                                  	; Initialize memory allocation table and page tables
   308                                  	; 16/11/2014
   309                                  	; 15/11/2014
   310                                  	; 07/11/2014
   311                                  	; 06/11/2014
   312                                  	; 05/11/2014
   313                                  	; 04/11/2014
   314                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   315                                  	;
   316                                  ;	xor	eax, eax
   317                                  ;	xor 	ecx, ecx
   318 0000032F B108                    	mov	cl, 8
   319 00000331 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   320 00000336 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   321                                  				   ; for the first 1 MB memory
   322                                  	;
   323 00000338 668B0D[1E690000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   324                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   325 0000033F 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   326 00000343 890D[A06B0000]          	mov	[free_pages], ecx
   327 00000349 668B15[20690000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   328                                  				   ; between 16 MB and 4 GB.	
   329 00000350 6609D2                  	or	dx, dx
   330 00000353 7413                    	jz	short mi_0
   331                                  	;
   332 00000355 6689D0                  	mov	ax, dx
   333 00000358 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   334 0000035B 0105[A06B0000]          	add	[free_pages], eax
   335 00000361 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   336 00000366 EB07                    	jmp	short mi_1
   337                                  mi_0:
   338 00000368 6689C8                  	mov	ax, cx
   339 0000036B 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   340                                  mi_1:
   341 0000036F A3[9C6B0000]            	mov	[memory_size], eax ; Total available memory in pages
   342                                  				   ; 1 alloc. tbl. bit = 1 memory page
   343                                  				   ; 32 allocation bits = 32 mem. pages   
   344                                  	;
   345 00000374 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   346 00000379 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   347                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   348                                  				   ;  --> x M.A.T. pages, if y = 0
   349 0000037C 66A3[B06B0000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   350 00000382 C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   351                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   352 00000385 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   353                                  	; Set/Calculate Kernel's Page Directory Address
   354 00000387 81C300001000            	add	ebx, MEM_ALLOC_TBL
   355 0000038D 891D[986B0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   356                                  				   ; just after the last M.A.T. page
   357                                  	;
   358 00000393 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   359 00000396 A3[A86B0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   360                                  	;			   ; (allocation status search must be 
   361                                  				   ; stopped after here)	
   362 0000039B 31C0                    	xor	eax, eax
   363 0000039D 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   364 0000039E 6651                    	push	cx
   365 000003A0 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   366                                  				   ; count of 32 allocation bits
   367 000003A3 F3AB                    	rep	stosd
   368 000003A5 6659                    	pop	cx
   369 000003A7 40                      	inc	eax		   ; 0	
   370 000003A8 80E11F                  	and	cl, 31		   ; remain bits
   371 000003AB 7412                    	jz	short mi_4
   372 000003AD 8907                    	mov	[edi], eax	   ; reset	
   373                                  mi_2:
   374 000003AF 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   375 000003B2 FEC9                    	dec	cl
   376 000003B4 7404                    	jz	short mi_3
   377 000003B6 FEC0                    	inc	al
   378 000003B8 EBF5                    	jmp	short mi_2
   379                                  mi_3:
   380 000003BA 28C0                    	sub	al, al	   	   ; 0
   381 000003BC 83C704                  	add	edi, 4		   ; 15/11/2014
   382                                  mi_4:
   383 000003BF 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   384 000003C2 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   385                                  	;	
   386 000003C4 B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   387                                  	;	
   388 000003C9 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   389 000003CB 7406                    	jz	short mi_5	  ; jump if EDI points to 
   390                                  				  ;         end of first 16 MB	
   391 000003CD D1E9                    	shr	ecx, 1		  ; convert to dword count
   392 000003CF D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   393 000003D1 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   394                                  				  ; (memory hole under 16 MB)
   395                                  mi_5:
   396 000003D3 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   397 000003D6 D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   398 000003D8 9C                      	pushf			  ; 16/11/2014		
   399 000003D9 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   400 000003DA F3AB                    	rep	stosd
   401 000003DC 40                      	inc	eax		  ; 0
   402 000003DD 9D                      	popf			  ; 16/11/2014
   403 000003DE 7305                    	jnc	short mi_6
   404 000003E0 6648                    	dec	ax		  ; eax = 0000FFFFh
   405 000003E2 AB                      	stosd
   406 000003E3 6640                    	inc	ax		  ; 0		
   407                                  mi_6:
   408 000003E5 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   409 000003E7 730A                    	jnb	short mi_7	  ; end of memory allocation table
   410                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   411 000003E9 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   412 000003EB 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   413 000003ED D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   414 000003EF D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   415 000003F1 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   416                                  mi_7:
   417                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   418 000003F3 BA00001000              	mov	edx, MEM_ALLOC_TBL
   419                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   420                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   421 000003F8 668B0D[B06B0000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   422 000003FF 89D7                    	mov	edi, edx
   423 00000401 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   424                                  				  ; byte offset in M.A.T.
   425                                  				  ; (1 M.A.T. byte points to 
   426                                  				  ;	      32768 bytes)
   427                                  				  ; Note: MEM_ALLOC_TBL address 
   428                                  				  ; must be aligned on 128 KB 
   429                                  				  ; boundary!
   430 00000404 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   431                                  	; eax = 0
   432 00000406 290D[A06B0000]          	sub	[free_pages], ecx ; 07/11/2014
   433                                  mi_8:
   434 0000040C 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   435                                  	;dec	bl
   436 0000040F FEC9                    	dec	cl
   437 00000411 7404                    	jz	short mi_9
   438 00000413 FEC0                    	inc	al
   439 00000415 EBF5                    	jmp	short mi_8
   440                                  mi_9:
   441                                  	;
   442                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   443                                  	;		(allocate pages for system page tables)
   444                                  
   445                                  	; edx = MEM_ALLOC_TBL
   446 00000417 8B0D[9C6B0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   447 0000041D 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   448 00000423 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   449                                  				 ; page table count (PDE count)
   450                                  	;
   451 00000426 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   452                                  	;
   453 00000427 41                      	inc	ecx		 ; +1 for kernel page directory	
   454                                  	;
   455 00000428 290D[A06B0000]          	sub	[free_pages], ecx ; 07/11/2014
   456                                  	;
   457 0000042E 8B35[986B0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   458 00000434 C1EE0C                  	shr	esi, 12		 ; convert to page number
   459                                  mi_10:
   460 00000437 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   461 00000439 89C3                    	mov	ebx, eax
   462 0000043B C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   463 0000043E 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   464                                  				 ;   to align on dword boundary
   465 00000441 83E01F                  	and	eax, 31		 ; set allocation bit position 
   466                                  				 ;  (bit 0 to bit 31)
   467                                  	;
   468 00000444 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   469                                  	;
   470 00000446 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   471                                  	;
   472 00000449 46                      	inc	esi		 ; next page table
   473 0000044A E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   474                                  				 ; (ecx = page table count + 1)		
   475                                  	;
   476 0000044C 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   477                                  	;
   478                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   479                                  	;
   480                                  	; Initialize Kernel's Page Directory
   481 0000044D 8B3D[986B0000]          	mov	edi, [k_page_dir]
   482 00000453 89F8                    	mov	eax, edi
   483 00000455 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   484                                  		     	      ; supervisor + read&write + present
   485 00000457 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   486                                  mi_11:
   487 00000459 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   488                                  			        ; EAX points to next page table
   489 0000045E AB                      	stosd
   490 0000045F E2F8                    	loop	mi_11
   491 00000461 29C0                    	sub	eax, eax	; Empty PDE
   492 00000463 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   493 00000467 29D1                    	sub	ecx, edx
   494 00000469 7402                    	jz	short mi_12
   495 0000046B F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   496                                  	;
   497                                  	; Initialization of Kernel's Page Directory is OK, here.
   498                                  mi_12:
   499                                  	; Initialize Kernel's Page Tables
   500                                  	;
   501                                  	; (EDI points to address of page table 0)
   502                                  	; eax = 0
   503 0000046D 8B0D[9C6B0000]          	mov	ecx, [memory_size] ; memory size in pages
   504 00000473 89CA                    	mov	edx, ecx	; (***)
   505 00000475 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   506                                  			     ; supervisor + read&write + present 	
   507                                  mi_13:
   508 00000477 AB                      	stosd
   509 00000478 0500100000              	add	eax, 4096	
   510 0000047D E2F8                    	loop	mi_13	
   511 0000047F 6681E2FF03              	and	dx, 1023	; (***)
   512 00000484 740B                    	jz	short mi_14
   513 00000486 66B90004                	mov	cx, 1024	
   514 0000048A 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   515 0000048D 31C0                    	xor	eax, eax
   516 0000048F F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   517                                  				; of the last page table
   518                                  mi_14:
   519                                  	;  Initialization of Kernel's Page Tables is OK, here.
   520                                  	;
   521 00000491 89F8                    	mov	eax, edi	; end of the last page table page
   522                                  			        ; (beginging of user space pages)
   523 00000493 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   524 00000496 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   525                                  				; aligning on dword boundary	
   526                                  	 
   527 00000498 A3[AC6B0000]            	mov	[first_page], eax
   528 0000049D A3[A46B0000]            	mov	[next_page], eax ; The first free page pointer
   529                                  				 ; for user programs
   530                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   531                                  	;
   532                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   533                                  	;
   534                                  	
   535                                  	; Enable paging
   536                                  	;
   537 000004A2 A1[986B0000]                    mov     eax, [k_page_dir]
   538 000004A7 0F22D8                  	mov	cr3, eax
   539 000004AA 0F20C0                  	mov	eax, cr0
   540 000004AD 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   541 000004B2 0F22C0                  	mov	cr0, eax
   542                                          ;jmp    KCODE:StartPMP
   543                                  
   544 000004B5 EA                      	db 0EAh 		; Opcode for far jump
   545 000004B6 [BC040000]                      dd StartPMP		; 32 bit offset
   546 000004BA 0800                    	dw KCODE		; kernel code segment descriptor
   547                                  
   548                                  
   549                                  StartPMP:
   550                                  	; 06/11//2014
   551                                  	; Clear video page 0
   552                                  	;
   553                                  	; Temporary Code
   554                                  	;
   555 000004BC B9E8030000              	mov	ecx, 80*25/2
   556 000004C1 BF00800B00              	mov	edi, 0B8000h
   557 000004C6 31C0                    	xor	eax, eax	; black background, black fore color
   558 000004C8 F3AB                    	rep	stosd
   559                                  	
   560                                  	; 19/08/2014
   561                                  	; Kernel Base Address = 0
   562                                  	; It is mapped to (physically) 0 in the page table.
   563                                  	; So, here is exactly 'StartPMP' address.
   564                                  	;
   565                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   566                                  	;;mov	esi, msgPM
   567                                  	;; 14/08/2015 (kernel version message will appear
   568                                  	;;	       when protected mode and paging is enabled)
   569 000004CA B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   570 000004CC BE[F0660000]            	mov	esi, msgKVER
   571 000004D1 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   572                                  	; 20/08/2014
   573 000004D6 E892010000              	call	printk
   574                                  
   575                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   576                                  	; // Set IRQ offsets
   577                                  	;
   578                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   579                                  	;
   580                                  					;; ICW1
   581 000004DB B011                    	mov	al, 11h			; Initialization sequence
   582 000004DD E620                    	out	20h, al			; 	8259A-1
   583                                  	; jmp 	$+2
   584 000004DF E6A0                    	out	0A0h, al		; 	8259A-2
   585                                  					;; ICW2
   586 000004E1 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   587 000004E3 E621                    	out	21h, al			;	for 8259A-1
   588                                  	; jmp 	$+2
   589 000004E5 B028                    	mov	al, 28h			; Start of hardware ints (28h)
   590 000004E7 E6A1                    	out	0A1h, al		; 	for 8259A-2
   591                                  					;
   592 000004E9 B004                    	mov	al, 04h			;; ICW3
   593 000004EB E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   594                                  	; jmp 	$+2
   595 000004ED B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   596 000004EF E6A1                    	out	0A1h, al		;
   597                                  					;; ICW4
   598 000004F1 B001                    	mov	al, 01h	 		;
   599 000004F3 E621                    	out	21h, al			; 	8086 mode, normal EOI	
   600                                  	; jmp 	$+2
   601 000004F5 E6A1                    	out	0A1h, al		;	for both chips.
   602                                  
   603                                  	;mov	al, 0FFh	; mask off all interrupts for now
   604                                  	;out	21h, al
   605                                  	;; jmp 	$+2
   606                                  	;out	0A1h, al
   607                                  
   608                                  	; 02/04/2015
   609                                  	; 26/03/2015 System call (INT 30h) modification
   610                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   611                                  	;
   612                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   613                                  	;  setup_idt:
   614                                  	;
   615                                          ;; 16/02/2015
   616                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   617                                  	; 21/08/2014 (timer_int)
   618 000004F7 BE[BC630000]            	mov	esi, ilist
   619 000004FC 8D3D[30690000]          	lea	edi, [idt]
   620                                  	; 26/03/2015
   621 00000502 B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   622                                  	; 02/04/2015
   623 00000507 BB00000800              	mov	ebx, 80000h
   624                                  rp_sidt1:
   625 0000050C AD                      	lodsd
   626 0000050D 89C2                    	mov	edx, eax
   627 0000050F 66BA008E                	mov	dx, 8E00h
   628 00000513 6689C3                  	mov	bx, ax
   629 00000516 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   630                                         			        ; /* interrupt gate - dpl=0, present */
   631 00000518 AB                      	stosd	; selector & offset bits 0-15 	
   632 00000519 89D0                    	mov	eax, edx
   633 0000051B AB                      	stosd	; attributes & offset bits 16-23
   634 0000051C E2EE                    	loop	rp_sidt1
   635 0000051E B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   636                                  rp_sidt2:
   637 00000520 AD                      	lodsd
   638 00000521 21C0                    	and	eax, eax
   639 00000523 7413                    	jz	short rp_sidt3
   640 00000525 89C2                    	mov	edx, eax
   641 00000527 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   642 0000052B 6689C3                  	mov	bx, ax
   643 0000052E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   644 00000530 AB                      	stosd
   645 00000531 89D0                    	mov	eax, edx
   646 00000533 AB                      	stosd
   647 00000534 E2EA                    	loop	rp_sidt2
   648 00000536 EB16                    	jmp	short sidt_OK
   649                                  rp_sidt3:
   650 00000538 B8[90090000]            	mov	eax, ignore_int
   651 0000053D 89C2                    	mov	edx, eax
   652 0000053F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   653 00000543 6689C3                  	mov	bx, ax
   654 00000546 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   655                                  rp_sidt4:
   656 00000548 AB                      	stosd
   657 00000549 92                      	xchg	eax, edx
   658 0000054A AB                      	stosd
   659 0000054B 92                      	xchg	edx, eax
   660 0000054C E2FA                    	loop	rp_sidt4
   661                                  sidt_OK: 
   662 0000054E 0F011D[B6630000]        	lidt 	[idtd]
   663                                  	;
   664                                  	; TSS descriptor setup ; 24/03/2015
   665 00000555 B8[306B0000]            	mov	eax, task_state_segment
   666 0000055A 66A3[AA630000]          	mov	[gdt_tss0], ax
   667 00000560 C1C010                  	rol	eax, 16
   668 00000563 A2[AC630000]            	mov	[gdt_tss1], al
   669 00000568 8825[AF630000]          	mov	[gdt_tss2], ah
   670 0000056E 66C705[966B0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   670 00000576 00                 
   671                                  		; 
   672                                  		; IO Map Base address (When this address points
   673                                  		; to end of the TSS, CPU does not use IO port 
   674                                  		; permission bit map for RING 3 IO permissions, 
   675                                  		; access to any IO ports in ring 3 will be forbidden.)
   676                                   		;
   677                                  	;mov	[tss.esp0], esp ; TSS offset 4
   678                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   679 00000577 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   680                                  			 ; occurs (or a system call -software INT- is requested)
   681                                  			 ; while cpu running in ring 3 (in user mode).				
   682                                  			 ; (Kernel stack pointer and segment will be loaded
   683                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   684 0000057B 0F00D8                  	ltr	ax  ; Load task register
   685                                  	;
   686                                  esp0_set0:
   687                                  	; 30/07/2015
   688 0000057E 8B0D[9C6B0000]          	mov 	ecx, [memory_size] ; memory size in pages
   689 00000584 C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   690 00000587 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   691                                  			  ; (kernel mode virtual address)
   692 0000058D 7605                    	jna	short esp0_set1
   693                                  	;
   694                                  	; If available memory > CORE (end of the 1st 4 MB)
   695                                  	; set stack pointer to CORE
   696                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   697                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   698 0000058F B900004000              	mov	ecx, CORE
   699                                  esp0_set1:
   700 00000594 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   701                                  esp0_set_ok:
   702                                  	; 30/07/2015 (**tss.esp0**) 
   703 00000596 8925[346B0000]          	mov	[tss.esp0], esp
   704 0000059C 66C705[386B0000]10-             mov     word [tss.ss0], KDATA
   704 000005A4 00                 
   705                                  	; 14/08/2015
   706                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   707                                  	;
   708                                  	;cli	; Disable interrupts (for CPU)
   709                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   710                                  	;
   711 000005A5 30C0                    	xor	al, al		; Enable all hardware interrupts!
   712 000005A7 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   713 000005A9 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   714 000005AB E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   715                                  				; (Even if related hardware component
   716                                  				;  does not exist!)
   717                                  	; Enable NMI 
   718 000005AD B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   719 000005AF E670                    	out  	70h, al
   720                                  	; 23/02/2015
   721 000005B1 90                      	nop
   722 000005B2 E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   723                                  				; for preventing unknown state (!?)
   724                                  	;
   725                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   726                                  	;
   727                                  	; 02/09/2014
   728                                  	;xor	bx, bx
   729                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   730                                  	; 27/02/2022	
   731 000005B4 31DB                    	xor	ebx, ebx
   732 000005B6 31D2                    	xor	edx, edx
   733 000005B8 B602                    	mov	dh, 2
   734 000005BA E8290F0000              	call	set_cpos
   735                                  	;
   736                                  	; 06/11/2014
   737                                  	; Temporary Code
   738                                  	;
   739 000005BF E8A2100000              	call	memory_info
   740                                  	; 14/08/2015
   741                                  	;call getch ; 28/02/2015
   742                                  drv_init:
   743 000005C4 FB                      	sti	; Enable Interrupts 
   744                                  	; 06/02/2015
   745 000005C5 8B15[90660000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   746 000005CB 668B1D[8E660000]        	mov	bx, [fd0_type] ; fd0, fd1
   747                                  	; 22/02/2015
   748 000005D2 6621DB                  	and	bx, bx
   749 000005D5 751B                    	jnz	short di1
   750                                  	;
   751 000005D7 09D2                    	or 	edx, edx
   752 000005D9 7529                    	jnz	short di2
   753                                  	;
   754                                  setup_error:
   755 000005DB BE[D7670000]            	mov 	esi, setup_error_msg
   756                                  psem:	
   757 000005E0 AC                      	lodsb
   758 000005E1 08C0                    	or	al, al
   759                                  	;jz	short haltx ; 22/02/2015
   760 000005E3 7426                    	jz	short di3
   761 000005E5 56                      	push	esi
   762 000005E6 31DB                    	xor	ebx, ebx ; 0
   763                                  			; Video page 0 (bl=0)
   764 000005E8 B407                    	mov	ah, 07h ; Black background, 
   765                                  			; light gray forecolor
   766 000005EA E8EF0D0000              	call	write_tty
   767 000005EF 5E                      	pop	esi
   768 000005F0 EBEE                    	jmp	short psem
   769                                  
   770                                  di1:
   771                                  	; supress 'jmp short T6'
   772                                  	;  (activate fdc motor control code)
   773 000005F2 66C705[EE060000]90-     	mov	word [T5], 9090h ; nop
   773 000005FA 90                 
   774                                  	;
   775                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   776                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   777                                  	;stosw
   778                                  	;mov 	ax, cs
   779                                  	;stosw
   780                                  	;; 16/02/2015
   781                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   782                                  	;
   783 000005FB E87C1F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   784                                  	;
   785 00000600 09D2                    	or	edx, edx
   786 00000602 7407                            jz      short di3
   787                                  di2:
   788 00000604 E8B91F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   789 00000609 72D0                            jc      short setup_error
   790                                  di3:
   791 0000060B E82A100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   792                                  	;
   793 00000610 E8C15C0000              	call	display_disks ; 07/03/2015  (Temporary)
   794                                  ;haltx:
   795                                  	; 14/08/2015
   796                                  	;call	getch ; 22/02/2015
   797 00000615 FB                      	sti	; Enable interrupts (for CPU)
   798                                  	; 14/08/2015
   799                                  	;mov 	ecx, 0FFFFFFFh
   800                                  	; 16/02/2022
   801 00000616 B9FFFF4F00              	mov 	ecx, 04FFFFFh
   802                                  md_info_msg_wait:
   803 0000061B 51                      	push 	ecx
   804 0000061C B001                    	mov	al, 1
   805 0000061E 8A25[C66B0000]          	mov 	ah, [ptty] ; active (current) video page
   806 00000624 E80C5A0000              	call	getc_n
   807 00000629 59                      	pop	ecx
   808 0000062A 7502                    	jnz	short md_info_msg_ok
   809 0000062C E2ED                    	loop	md_info_msg_wait
   810                                  md_info_msg_ok:
   811                                  	; 30/06/2015
   812 0000062E E89A2C0000              	call	sys_init
   813                                  	;
   814                                  	;jmp 	cpu_reset ; 22/02/2015
   815                                  hang:
   816                                  	; 27/02/2022
   817 00000633 29C0                    	sub	eax, eax
   818                                  _hang: 
   819                                  	; 23/02/2015
   820                                  	;sti			; Enable interrupts
   821 00000635 F4                      	hlt
   822                                  	;
   823                                  	;nop
   824                                  	;; 03/12/2014
   825                                  	;; 28/08/2014
   826                                  	;mov	ah, 11h
   827                                  	;call	getc
   828                                  	;jz      _c8
   829                                  	;
   830                                  	; 23/02/2015
   831                                  	; 06/02/2015
   832                                  	; 07/09/2014
   833 00000636 31DB                    	xor	ebx, ebx
   834 00000638 8A1D[C66B0000]          	mov	bl, [ptty]	; active_page
   835 0000063E 89DE                    	mov	esi, ebx
   836 00000640 66D1E6                  	shl 	si, 1
   837 00000643 81C6[C86B0000]          	add	esi, ttychr
   838 00000649 668B06                  	mov	ax, [esi]
   839                                  	;and	ax, ax
   840                                  	;;jz	short _c8
   841                                  	;jz	short hang
   842                                  	; 27/02/2022
   843 0000064C 21C0                    	and	eax, eax
   844 0000064E 74E5                    	jz	short _hang
   845 00000650 66C7060000              	mov	word [esi], 0
   846 00000655 80FB03                  	cmp	bl, 3		; Video page 3
   847                                  	;jb	short _c8
   848 00000658 72D9                    	jb	short hang
   849                                  	;	
   850                                  	; 02/09/2014
   851 0000065A B40E                    	mov	ah, 0Eh		; Yellow character 
   852                                  				; on black background
   853                                  	; 27/02/2022 (32 bit reg push-pop)
   854                                  	; 07/09/2014
   855                                  nxtl:
   856                                  	;push	bx
   857 0000065C 53                      	push	ebx
   858                                  	;
   859                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   860                                  				; bh = 0 (video mode)
   861                                  				; Retro UNIX 386 v1 - Video Mode 0
   862                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   863 0000065D 50                      	push	eax
   864 0000065E E87B0D0000              	call 	write_tty
   865 00000663 58                      	pop	eax
   866                                  	;pop	bx
   867 00000664 5B                      	pop	ebx
   868 00000665 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   869                                  	;jne	short _c8
   870 00000667 75CA                    	jne	short hang
   871 00000669 B00A                    	mov	al, 0Ah		; next line
   872 0000066B EBEF                    	jmp	short nxtl
   873                                  	
   874                                  ;_c8:
   875                                  ;	; 25/08/2014
   876                                  ;	cli				; Disable interrupts
   877                                  ;	mov	al, [scounter + 1]
   878                                  ;	and	al, al
   879                                  ;	jnz	hang
   880                                  ;	call	rtc_p
   881                                  ;	jmp     hang
   882                                  
   883                                  
   884                                  	; 27/08/2014
   885                                  	; 20/08/2014
   886                                  printk:
   887                                          ;mov    edi, [scr_row]
   888                                  pkl:
   889 0000066D AC                      	lodsb
   890 0000066E 08C0                    	or 	al, al
   891 00000670 7404                    	jz	short pkr
   892 00000672 66AB                    	stosw
   893 00000674 EBF7                    	jmp	short pkl
   894                                  pkr:
   895 00000676 C3                      	retn
   896                                  
   897                                  ; 25/07/2015
   898                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   899                                  ; 17/02/2015
   900                                  ; 06/02/2015 (unix386.s)
   901                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   902                                  ;
   903                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   904                                  ;
   905                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   906                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   907                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   908                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   909                                  ;									       :
   910                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   911                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   912                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   913                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   914                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   915                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   916                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   917                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   918                                  ;-------------------------------------------------------------------------------
   919                                  ;
   920                                  
   921                                  timer_int:	; IRQ 0
   922                                  ;int_08h:	; Timer
   923                                  	; 14/10/2015
   924                                  	; Here, we are simulating system call entry (for task switch)
   925                                  	; (If multitasking is enabled, 
   926                                  	; 'clock' procedure may jump to 'sysrelease')
   927 00000677 1E                      	push	ds
   928 00000678 06                      	push	es
   929 00000679 0FA0                    	push	fs
   930 0000067B 0FA8                    	push	gs
   931 0000067D 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   932 0000067E 66B91000                	mov     cx, KDATA
   933 00000682 8ED9                            mov     ds, cx
   934 00000684 8EC1                            mov     es, cx
   935 00000686 8EE1                            mov     fs, cx
   936 00000688 8EE9                            mov     gs, cx
   937                                  	;
   938 0000068A 0F20D9                  	mov	ecx, cr3
   939 0000068D 890D[30070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   940                                  	;
   941 00000693 3B0D[986B0000]          	cmp 	ecx, [k_page_dir]
   942 00000699 741F                    	je	short T3
   943                                  	;
   944                                  	; timer interrupt has been occurred while OS is in user mode
   945 0000069B A3[5C6F0000]            	mov 	[u.r0], eax
   946 000006A0 89E1                    	mov	ecx, esp
   947 000006A2 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   948 000006A5 890D[546F0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   949 000006AB 8925[586F0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   950                                  	;
   951 000006B1 8B0D[986B0000]          	mov	ecx, [k_page_dir]
   952 000006B7 0F22D9                  	mov	cr3, ecx
   953                                  T3:
   954 000006BA FB                      	sti				; INTERRUPTS BACK ON
   955 000006BB 66FF05[146C0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   956 000006C2 7507                    	JNZ	short T4		; GO TO TEST_DAY
   957 000006C4 66FF05[166C0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   958                                  T4:					; TEST_DAY
   959 000006CB 66833D[166C0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   960 000006D3 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   961 000006D5 66813D[146C0000]B0-     	CMP	word [TIMER_LOW],0B0H
   961 000006DD 00                 
   962 000006DE 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   963                                  
   964                                  ;-----	TIMER HAS GONE 24 HOURS
   965                                  	;;SUB	AX,AX
   966                                  	;MOV	[TIMER_HIGH],AX
   967                                  	;MOV	[TIMER_LOW],AX
   968 000006E0 29C0                    	sub	eax, eax
   969 000006E2 A3[146C0000]            	mov	[TIMER_LH], eax
   970                                  	;	
   971 000006E7 C605[186C0000]01        	MOV	byte [TIMER_OFL],1
   972                                  
   973                                  ;-----	TEST FOR DISKETTE TIME OUT
   974                                  
   975                                  T5:
   976                                  	; 23/12/2014
   977 000006EE EB1D                    	jmp	short T6		; will be replaced with nop, nop
   978                                  					; (9090h) if a floppy disk
   979                                  					; is detected.
   980                                  	;mov	al,[CS:MOTOR_COUNT]
   981 000006F0 A0[1B6C0000]            	mov	al, [MOTOR_COUNT]
   982 000006F5 FEC8                    	dec	al
   983                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   984 000006F7 A2[1B6C0000]            	mov	[MOTOR_COUNT], al
   985                                  	;mov	[ORG_MOTOR_COUNT], al
   986 000006FC 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   987 000006FE B0F0                    	mov 	al,0F0h
   988                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   989 00000700 2005[1A6C0000]          	and	[MOTOR_STATUS], al
   990                                  	;and	[ORG_MOTOR_STATUS], al
   991 00000706 B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   992                                  					; bit 2 = enable controller
   993                                  					;	1 = normal operation
   994                                  					;	0 = reset	
   995                                  					; bit 0, 1 = drive select
   996                                  					; bit 4-7 = motor running bits 
   997 00000708 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   998 0000070C EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
   999                                  T6:	
  1000                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1001                                  					; TIMER TICK INTERRUPT
  1002                                  	;;inc	word [wait_count] ;;27/02/2015
  1003                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1004                                  	;;;;cli
  1005                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1006 0000070D FF15[28070000]          	call	[x_timer] ; 14/05/2015
  1007                                  T7:
  1008                                  	; 14/10/2015
  1009 00000713 B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1010 00000715 FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1011 00000716 E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1012                                  	;
  1013 00000718 A1[30070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1014 0000071D 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1015                                  	;
  1016 00000720 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1017                                  	;
  1018 00000721 0FA9                    	pop	gs
  1019 00000723 0FA1                    	pop	fs
  1020 00000725 07                      	pop	es
  1021 00000726 1F                      	pop	ds
  1022 00000727 CF                      	iretd	; return from interrupt
  1023                                  
  1024                                  
  1025                                  ; ////////////////
  1026                                  
  1027                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1028                                  x_timer:
  1029 00000728 [34070000]              	dd 	u_timer	; (temporary demo code)	; 14/05/2015
  1030                                  	;dd	clock
  1031                                  
  1032                                  ; 23/02/2022 - Real time clock (digital) output demo (sys emt)
  1033                                  x_rtci:
  1034 0000072C [690A0000]              	dd	rtc_p	; (temporary demo code)	; 23/02/2022
  1035                                  
  1036                                  ; 14/10/2015
  1037 00000730 00000000                cr3reg: dd 0
  1038                                  
  1039                                  	; 06/02/2015
  1040                                  	; 07/09/2014
  1041                                  	; 21/08/2014
  1042                                  u_timer:
  1043                                  	; 27/02/2022
  1044                                  	; 12/02/2022
  1045                                  ;timer_int:	; IRQ 0
  1046                                  	; 06/02/2015
  1047                                  	;push	eax
  1048                                  	;push	edx
  1049                                  	;push	ecx
  1050                                  	;push	ebx
  1051                                  	;push	ds
  1052                                  	;push	es
  1053                                  	;mov	eax, KDATA
  1054                                  	;mov	ds, ax
  1055                                  	;mov	es, ax
  1056 00000734 FF05[DC6B0000]          	inc	dword [tcount]
  1057 0000073A BB[60670000]            	mov	ebx, tcountstr + 4
  1058                                  	;mov	ax, [tcount]
  1059                                  	; 27/02/2022
  1060 0000073F A1[DC6B0000]            	mov	eax, [tcount]
  1061                                  	;mov	ecx, 10
  1062 00000744 31C9                    	xor	ecx, ecx
  1063 00000746 B10A                    	mov	cl, 10
  1064                                  rp_divtcnt:
  1065 00000748 31D2                    	xor	edx, edx
  1066 0000074A F7F1                    	div	ecx
  1067 0000074C 80C230                  	add	dl, 30h
  1068 0000074F 8813                    	mov	[ebx], dl
  1069                                  	;or	ax, ax
  1070                                  	; 27/02/2022
  1071 00000751 09C0                    	or	eax, eax
  1072 00000753 7403                    	jz	short print_lzero
  1073 00000755 4B                      	dec	ebx
  1074 00000756 EBF0                    	jmp	short rp_divtcnt
  1075                                  print_lzero:
  1076 00000758 81FB[5C670000]          	cmp	ebx, tcountstr
  1077 0000075E 7606                    	jna	short print_tcount
  1078 00000760 4B                      	dec	ebx
  1079 00000761 C60330                   	mov	byte [ebx], 30h
  1080 00000764 EBF2                    	jmp	short print_lzero
  1081                                  print_tcount:
  1082 00000766 56                      	push	esi
  1083 00000767 57                      	push	edi
  1084 00000768 BE[38670000]            	mov	esi, timer_msg ; Timer interrupt message
  1085                                  	;; 07/09/2014
  1086                                  	;mov	bx, 1		; Video page 1
  1087                                  	; 12/02/2022
  1088                                  	;mov	bx, 6		; Video page 6
  1089                                  	; 27/02/2022
  1090 0000076D 29DB                    	sub	ebx, ebx
  1091 0000076F B306                    	mov	bl, 6	; Video page 6
  1092                                  ptmsg:
  1093 00000771 AC                      	lodsb
  1094 00000772 08C0                    	or	al, al
  1095 00000774 740D                    	jz	short ptmsg_ok
  1096 00000776 56                      	push	esi
  1097                                  	;push	bx
  1098                                  	; 27/02/2022
  1099 00000777 53                              push	ebx
  1100 00000778 B42F                            mov     ah,  2Fh ; Green background, white forecolor
  1101 0000077A E85F0C0000              	call 	write_tty
  1102                                  	;pop	bx
  1103                                  	; 27/02/2022
  1104 0000077F 5B                      	pop	ebx
  1105 00000780 5E                      	pop	esi
  1106 00000781 EBEE                    	jmp	short ptmsg
  1107                                  	;; 27/08/2014
  1108                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1109                                  	;call	printk
  1110                                  	;
  1111                                  ptmsg_ok:
  1112                                  	; 07/09/2014
  1113                                  	;xor	dx, dx		; column 0, row 0
  1114                                  	; 27/02/2022
  1115 00000783 31D2                    	xor	edx, edx
  1116 00000785 E85E0D0000              	call	set_cpos	; set cursor position to 0,0 
  1117                                  	; 23/02/2015
  1118                                  	; 25/08/2014
  1119                                  	;mov	ebx, scounter		; (seconds counter)
  1120                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1121                                  ;	dec	byte [scounter+1]
  1122                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1123                                  ;	jns	short u_timer_retn
  1124                                  	; 26/02/2015
  1125                                  ;	call	rtc_p
  1126                                  ;	mov	ebx, scounter		; (seconds counter)
  1127                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1128                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1129                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1130                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1131                                  ;	mov	byte [ebx], 5
  1132                                  ;	inc	byte [ebx+1] ; 19
  1133                                  ;;timer_eoi:
  1134                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1135                                  ;;	out	20h, al	; 8259 PORT
  1136                                  	;
  1137                                  ;u_timer_retn:  ; 06/02/2015
  1138 0000078A 5F                      	pop	edi
  1139 0000078B 5E                      	pop	esi
  1140                                  	;pop	es
  1141                                  	;pop	ds
  1142                                  	;pop	ebx
  1143                                  	;pop	ecx
  1144                                  	;pop	edx
  1145                                  	;pop	eax
  1146                                  	;iret
  1147 0000078C C3                      	retn	; 06/02/2015
  1148                                  
  1149                                  	; 28/08/2014
  1150                                  irq0:
  1151 0000078D 6A00                            push 	dword 0
  1152 0000078F EB48                    	jmp	short which_irq
  1153                                  irq1:
  1154 00000791 6A01                            push 	dword 1
  1155 00000793 EB44                    	jmp	short which_irq
  1156                                  irq2:
  1157 00000795 6A02                            push 	dword 2
  1158 00000797 EB40                    	jmp	short which_irq
  1159                                  irq3:
  1160                                  	; 20/11/2015
  1161                                  	; 24/10/2015
  1162 00000799 2EFF15[DE390000]        	call	dword [cs:com2_irq3]
  1163 000007A0 6A03                    	push 	dword 3
  1164 000007A2 EB35                    	jmp	short which_irq
  1165                                  irq4:
  1166                                  	; 20/11/2015
  1167                                  	; 24/10/2015
  1168 000007A4 2EFF15[DA390000]        	call	dword [cs:com1_irq4]
  1169 000007AB 6A04                            push 	dword 4
  1170 000007AD EB2A                    	jmp	short which_irq
  1171                                  irq5:
  1172 000007AF 6A05                            push 	dword 5
  1173 000007B1 EB26                    	jmp	short which_irq
  1174                                  irq6:
  1175 000007B3 6A06                            push 	dword 6
  1176 000007B5 EB22                    	jmp	short which_irq
  1177                                  irq7:
  1178 000007B7 6A07                            push 	dword 7
  1179 000007B9 EB1E                    	jmp	short which_irq
  1180                                  irq8:
  1181 000007BB 6A08                            push 	dword 8
  1182 000007BD EB1A                    	jmp	short which_irq
  1183                                  irq9:
  1184 000007BF 6A09                            push 	dword 9
  1185 000007C1 EB16                    	jmp	short which_irq
  1186                                  irq10:
  1187 000007C3 6A0A                            push 	dword 10
  1188 000007C5 EB12                    	jmp	short which_irq
  1189                                  irq11:
  1190 000007C7 6A0B                            push 	dword 11
  1191 000007C9 EB0E                    	jmp	short which_irq
  1192                                  irq12:
  1193 000007CB 6A0C                            push 	dword 12
  1194 000007CD EB0A                    	jmp	short which_irq
  1195                                  irq13:
  1196 000007CF 6A0D                            push 	dword 13
  1197 000007D1 EB06                    	jmp	short which_irq
  1198                                  irq14:
  1199 000007D3 6A0E                            push 	dword 14
  1200 000007D5 EB02                    	jmp	short which_irq
  1201                                  irq15:
  1202 000007D7 6A0F                            push 	dword 15
  1203                                  	;jmp	short which_irq
  1204                                  
  1205                                  	; 27/02/2022
  1206                                  	; 19/10/2015
  1207                                  	; 29/08/2014
  1208                                  	; 21/08/2014
  1209                                  which_irq:
  1210 000007D9 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1211 000007DC 53                      	push	ebx
  1212 000007DD 56                      	push	esi
  1213 000007DE 57                      	push	edi
  1214 000007DF 1E                      	push 	ds
  1215 000007E0 06                      	push 	es
  1216                                  	;
  1217 000007E1 88C3                    	mov	bl, al
  1218                                  	;
  1219 000007E3 B810000000              	mov	eax, KDATA
  1220 000007E8 8ED8                    	mov	ds, ax
  1221 000007EA 8EC0                    	mov	es, ax
  1222                                  	; 19/10/2015
  1223 000007EC FC                      	cld
  1224                                          ; 27/08/2014
  1225 000007ED 8105[E8660000]A000-             add     dword [scr_row], 0A0h
  1225 000007F5 0000               
  1226                                  	;
  1227 000007F7 B417                    	mov	ah, 17h	; blue (1) background, 
  1228                                  			; light gray (7) forecolor
  1229 000007F9 8B3D[E8660000]                  mov     edi, [scr_row]
  1230 000007FF B049                    	mov	al, 'I'
  1231 00000801 66AB                    	stosw
  1232 00000803 B052                    	mov	al, 'R'
  1233 00000805 66AB                    	stosw
  1234 00000807 B051                    	mov	al, 'Q'
  1235 00000809 66AB                    	stosw
  1236 0000080B B020                    	mov	al, ' '
  1237 0000080D 66AB                    	stosw
  1238 0000080F 88D8                    	mov	al, bl
  1239 00000811 3C0A                    	cmp	al, 10
  1240 00000813 7208                    	jb	short iix
  1241 00000815 B031                    	mov	al, '1'
  1242 00000817 66AB                    	stosw
  1243 00000819 88D8                    	mov	al, bl
  1244 0000081B 2C0A                    	sub	al, 10
  1245                                  iix:
  1246 0000081D 0430                    	add	al, '0'
  1247 0000081F 66AB                    	stosw
  1248 00000821 B020                    	mov	al, ' '
  1249 00000823 66AB                    	stosw
  1250 00000825 B021                    	mov	al, '!'
  1251 00000827 66AB                    	stosw
  1252 00000829 B020                    	mov	al, ' '
  1253 0000082B 66AB                    	stosw
  1254                                  	; 23/02/2015
  1255 0000082D 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1256                                  	;jna	iiret
  1257                                  	; 27/02/2022
  1258 00000830 7604                    	jna	short iiz
  1259                                  iiy:
  1260 00000832 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1261 00000834 E6A0                    	out	0A0h, al ; the 2nd 8259
  1262                                  iiz:
  1263 00000836 E983010000              	jmp     iiret
  1264                                  	;
  1265                                  	; 22/08/2014
  1266                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1267                                  	;out	20h, al	; 8259 PORT
  1268                                  	;
  1269                                  	;pop	es
  1270                                  	;pop	ds
  1271                                  	;pop	edi
  1272                                  	;pop	esi
  1273                                  	;pop	ebx
  1274                                  	;pop 	eax
  1275                                  	;iret
  1276                                  
  1277                                  	; 02/04/2015
  1278                                  	; 25/08/2014
  1279                                  exc0:
  1280 0000083B 6A00                            push 	dword 0
  1281 0000083D E990000000                      jmp     cpu_except
  1282                                  exc1:
  1283 00000842 6A01                            push 	dword 1
  1284 00000844 E989000000                      jmp     cpu_except
  1285                                  exc2:
  1286 00000849 6A02                            push 	dword 2
  1287 0000084B E982000000                      jmp     cpu_except
  1288                                  exc3:
  1289 00000850 6A03                            push 	dword 3
  1290 00000852 EB7E                            jmp     cpu_except
  1291                                  exc4:
  1292 00000854 6A04                            push 	dword 4
  1293 00000856 EB7A                            jmp     cpu_except
  1294                                  exc5:
  1295 00000858 6A05                            push 	dword 5
  1296 0000085A EB76                            jmp     cpu_except
  1297                                  exc6:
  1298 0000085C 6A06                            push 	dword 6
  1299 0000085E EB72                            jmp     cpu_except
  1300                                  exc7:
  1301 00000860 6A07                            push 	dword 7
  1302 00000862 EB6E                            jmp     cpu_except
  1303                                  exc8:
  1304                                  	; [esp] = Error code
  1305 00000864 6A08                            push 	dword 8
  1306 00000866 EB5C                            jmp     cpu_except_en
  1307                                  exc9:
  1308 00000868 6A09                            push 	dword 9
  1309 0000086A EB66                            jmp     cpu_except
  1310                                  exc10:
  1311                                  	; [esp] = Error code
  1312 0000086C 6A0A                            push 	dword 10
  1313 0000086E EB54                            jmp     cpu_except_en
  1314                                  exc11:
  1315                                  	; [esp] = Error code
  1316 00000870 6A0B                            push 	dword 11
  1317 00000872 EB50                            jmp     cpu_except_en
  1318                                  exc12:
  1319                                  	; [esp] = Error code
  1320 00000874 6A0C                            push 	dword 12
  1321 00000876 EB4C                            jmp     cpu_except_en
  1322                                  exc13:
  1323                                  	; [esp] = Error code
  1324 00000878 6A0D                            push 	dword 13
  1325 0000087A EB48                            jmp     cpu_except_en
  1326                                  exc14:
  1327                                  	; [esp] = Error code
  1328 0000087C 6A0E                            push 	dword 14
  1329 0000087E EB44                    	jmp	short cpu_except_en
  1330                                  exc15:
  1331 00000880 6A0F                            push 	dword 15
  1332 00000882 EB4E                            jmp     cpu_except
  1333                                  exc16:
  1334 00000884 6A10                            push 	dword 16
  1335 00000886 EB4A                            jmp     cpu_except
  1336                                  exc17:
  1337                                  	; [esp] = Error code
  1338 00000888 6A11                            push 	dword 17
  1339 0000088A EB38                    	jmp	short cpu_except_en
  1340                                  exc18:
  1341 0000088C 6A12                            push 	dword 18
  1342 0000088E EB42                    	jmp	short cpu_except
  1343                                  exc19:
  1344 00000890 6A13                            push 	dword 19
  1345 00000892 EB3E                    	jmp	short cpu_except
  1346                                  exc20:
  1347 00000894 6A14                            push 	dword 20
  1348 00000896 EB3A                    	jmp	short cpu_except
  1349                                  exc21:
  1350 00000898 6A15                            push 	dword 21
  1351 0000089A EB36                    	jmp	short cpu_except
  1352                                  exc22:
  1353 0000089C 6A16                            push 	dword 22
  1354 0000089E EB32                    	jmp	short cpu_except
  1355                                  exc23:
  1356 000008A0 6A17                            push 	dword 23
  1357 000008A2 EB2E                    	jmp	short cpu_except
  1358                                  exc24:
  1359 000008A4 6A18                            push 	dword 24
  1360 000008A6 EB2A                    	jmp	short cpu_except
  1361                                  exc25:
  1362 000008A8 6A19                            push 	dword 25
  1363 000008AA EB26                    	jmp	short cpu_except
  1364                                  exc26:
  1365 000008AC 6A1A                            push 	dword 26
  1366 000008AE EB22                    	jmp	short cpu_except
  1367                                  exc27:
  1368 000008B0 6A1B                            push 	dword 27
  1369 000008B2 EB1E                    	jmp	short cpu_except
  1370                                  exc28:
  1371 000008B4 6A1C                            push 	dword 28
  1372 000008B6 EB1A                    	jmp	short cpu_except
  1373                                  exc29:
  1374 000008B8 6A1D                            push 	dword 29
  1375 000008BA EB16                    	jmp	short cpu_except
  1376                                  exc30:
  1377 000008BC 6A1E                            push 	dword 30
  1378 000008BE EB04                    	jmp	short cpu_except_en
  1379                                  exc31:
  1380 000008C0 6A1F                            push 	dword 31
  1381 000008C2 EB0E                            jmp     short cpu_except
  1382                                  
  1383                                  	; 27/02/2022
  1384                                  	; 19/10/2015
  1385                                  	; 19/09/2015
  1386                                  	; 01/09/2015
  1387                                  	; 28/08/2015
  1388                                  	; 28/08/2014
  1389                                  cpu_except_en:
  1390 000008C4 87442404                	xchg	eax, [esp+4] ; Error code
  1391 000008C8 36A3[486C0000]          	mov	[ss:error_code], eax
  1392 000008CE 58                      	pop	eax  ; Exception number
  1393 000008CF 870424                  	xchg	eax, [esp]
  1394                                  		; eax = eax before exception
  1395                                  		; [esp] -> exception number
  1396                                  		; [esp+4] -> EIP to return
  1397                                  	; 19/10/2015
  1398                                  	; 19/09/2015
  1399                                  	; 01/09/2015
  1400                                  	; 28/08/2015
  1401                                  	; 29/08/2014
  1402                                  	; 28/08/2014
  1403                                  	; 25/08/2014
  1404                                  	; 21/08/2014
  1405                                  cpu_except:	; CPU Exceptions
  1406 000008D2 FC                      	cld
  1407 000008D3 870424                  	xchg	eax, [esp] 
  1408                                  		; eax = Exception number
  1409                                  		; [esp] = eax (before exception)	
  1410 000008D6 53                      	push	ebx
  1411 000008D7 56                      	push	esi
  1412 000008D8 57                      	push	edi
  1413 000008D9 1E                      	push 	ds
  1414 000008DA 06                      	push 	es
  1415                                  	; 28/08/2015
  1416 000008DB 66BB1000                	mov	bx, KDATA
  1417 000008DF 8EDB                    	mov	ds, bx
  1418 000008E1 8EC3                    	mov	es, bx
  1419 000008E3 0F20DB                  	mov	ebx, cr3
  1420 000008E6 53                      	push	ebx ; (*) page directory
  1421                                  	; 19/10/2015
  1422 000008E7 FC                      	cld
  1423                                  	; 25/03/2015
  1424 000008E8 8B1D[986B0000]          	mov	ebx, [k_page_dir]
  1425 000008EE 0F22DB                  	mov	cr3, ebx
  1426                                  	; 28/08/2015
  1427 000008F1 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1428 000008F4 7513                    	jne	short cpu_except_nfp
  1429 000008F6 E88C270000              	call	page_fault_handler
  1430 000008FB 21C0                    	and 	eax, eax
  1431                                          ;jz	iiretp ; 01/09/2015
  1432                                  	; 27/02/2022
  1433 000008FD 7505                    	jnz	short cpu_except_pf
  1434 000008FF E9B6000000              	jmp	iiretp
  1435                                  cpu_except_pf:
  1436 00000904 B80E000000              	mov	eax, 0Eh ; 14
  1437                                  cpu_except_nfp:
  1438                                  	; 02/04/2015
  1439 00000909 BB[33060000]            	mov	ebx, hang
  1440 0000090E 875C241C                	xchg	ebx, [esp+28]
  1441                                  		; EIP (points to instruction which faults)
  1442                                  	  	; New EIP (hang)
  1443 00000912 891D[4C6C0000]          	mov	[FaultOffset], ebx
  1444 00000918 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1445 00000920 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1446                                  	;
  1447 00000928 88C4                    	mov	ah, al
  1448 0000092A 240F                    	and	al, 0Fh
  1449 0000092C 3C09                    	cmp	al, 9
  1450 0000092E 7602                    	jna	short h1ok
  1451 00000930 0407                    	add	al, 'A'-':'
  1452                                  h1ok:
  1453 00000932 D0EC                    	shr	ah, 1
  1454 00000934 D0EC                    	shr	ah, 1
  1455 00000936 D0EC                    	shr	ah, 1
  1456 00000938 D0EC                    	shr	ah, 1
  1457 0000093A 80FC09                  	cmp	ah, 9
  1458 0000093D 7603                    	jna	short h2ok
  1459 0000093F 80C407                  	add	ah, 'A'-':'
  1460                                  h2ok:	
  1461 00000942 86E0                    	xchg 	ah, al	
  1462 00000944 66053030                	add	ax, '00'
  1463 00000948 66A3[74670000]          	mov	[excnstr], ax
  1464                                  	;
  1465                                  	; 29/08/2014
  1466 0000094E A1[4C6C0000]            	mov	eax, [FaultOffset]
  1467 00000953 51                      	push	ecx
  1468 00000954 52                      	push	edx
  1469 00000955 89E3                    	mov	ebx, esp
  1470                                  	; 28/08/2015
  1471 00000957 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1472                                  			  ; to hexadecimal string
  1473                                  	;mov	ecx, 10	    ; divisor to convert	
  1474                                  			    ; binary number to decimal string
  1475                                  b2d1:
  1476 0000095C 31D2                    	xor	edx, edx
  1477 0000095E F7F1                    	div	ecx
  1478                                  	;push	dx
  1479                                  	; 27/02/2022
  1480 00000960 52                      	push	edx
  1481 00000961 39C8                    	cmp	eax, ecx
  1482 00000963 73F7                    	jnb	short b2d1
  1483 00000965 BF[7F670000]            	mov	edi, EIPstr ; EIP value
  1484                                  			    ; points to instruction which faults	
  1485                                  	; 28/08/2015
  1486 0000096A 89C2                    	mov	edx, eax
  1487                                  b2d2:
  1488                                  	;add	al, '0'
  1489 0000096C 8A82[22170000]          	mov	al, [edx+hexchrs]
  1490 00000972 AA                      	stosb		    ; write hexadecimal digit to its place	
  1491 00000973 39E3                    	cmp	ebx, esp
  1492 00000975 7605                    	jna	short b2d3
  1493                                  	; 27/02/2022
  1494 00000977 58                      	pop	eax
  1495                                  	;pop	ax
  1496 00000978 88C2                    	mov	dl, al
  1497 0000097A EBF0                    	jmp	short b2d2
  1498                                  b2d3:
  1499 0000097C B068                    	mov 	al, 'h' ; 28/08/2015
  1500 0000097E AA                      	stosb
  1501 0000097F B020                    	mov	al, 20h	    ; space
  1502 00000981 AA                      	stosb
  1503 00000982 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1504 00000984 AA                      	stosb
  1505                                  	;
  1506 00000985 5A                      	pop	edx
  1507 00000986 59                      	pop	ecx
  1508                                  	;
  1509 00000987 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1510                                  			; white (F) forecolor
  1511 00000989 BE[64670000]            	mov	esi, exc_msg ; message offset
  1512                                  	;
  1513 0000098E EB11                    	jmp	short piemsg
  1514                                  	;
  1515                                          ;add    dword [scr_row], 0A0h
  1516                                          ;mov    edi, [scr_row]
  1517                                          ;
  1518                                  	;call 	printk
  1519                                  	;
  1520                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1521                                  	;out	20h, al	; 8259 PORT
  1522                                  	;
  1523                                  	;pop	es
  1524                                  	;pop	ds
  1525                                  	;pop	edi
  1526                                  	;pop	esi
  1527                                  	;pop 	eax
  1528                                  	;iret
  1529                                  	
  1530                                  	; 28/08/2015
  1531                                  	; 23/02/2015
  1532                                  	; 20/08/2014
  1533                                  ignore_int:
  1534 00000990 50                      	push	eax
  1535 00000991 53                      	push	ebx ; 23/02/2015
  1536 00000992 56                      	push	esi
  1537 00000993 57                      	push	edi
  1538 00000994 1E                      	push 	ds
  1539 00000995 06                      	push 	es
  1540                                  	; 28/08/2015
  1541 00000996 0F20D8                  	mov	eax, cr3
  1542 00000999 50                      	push	eax ; (*) page directory
  1543                                  	;
  1544 0000099A B467                    	mov	ah, 67h	; brown (6) background, 
  1545                                  			; light gray (7) forecolor
  1546 0000099C BE[22670000]            	mov	esi, int_msg ; message offset
  1547                                  piemsg:
  1548                                          ; 27/08/2014
  1549 000009A1 8105[E8660000]A000-             add     dword [scr_row], 0A0h
  1549 000009A9 0000               
  1550 000009AB 8B3D[E8660000]                  mov     edi, [scr_row]
  1551                                          ;
  1552 000009B1 E8B7FCFFFF              	call 	printk
  1553                                  	;
  1554                                  	; 23/02/2015
  1555 000009B6 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1556 000009B8 E6A0                    	out	0A0h, al ; the 2nd 8259
  1557                                  iiretp: ; 01/09/2015
  1558                                  	; 28/08/2015
  1559 000009BA 58                      	pop	eax ; (*) page directory
  1560 000009BB 0F22D8                  	mov	cr3, eax
  1561                                  	;
  1562                                  iiret:
  1563                                  	; 22/08/2014
  1564 000009BE B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1565 000009C0 E620                    	out	20h, al	; 8259 PORT
  1566                                  	;
  1567 000009C2 07                      	pop	es
  1568 000009C3 1F                      	pop	ds
  1569 000009C4 5F                      	pop	edi
  1570 000009C5 5E                      	pop	esi
  1571 000009C6 5B                      	pop	ebx ; 29/08/2014
  1572 000009C7 58                      	pop 	eax
  1573 000009C8 CF                      	iretd
  1574                                  
  1575                                  	; 23/02/2022
  1576                                  	; 26/02/2015
  1577                                  	; 07/09/2014
  1578                                  	; 25/08/2014
  1579                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1580                                  	; 22/08/2014
  1581 000009C9 50                      	push	eax
  1582 000009CA 53                      	push	ebx ; 29/08/2014
  1583 000009CB 56                      	push	esi
  1584 000009CC 57                      	push	edi
  1585 000009CD 1E                      	push 	ds
  1586 000009CE 06                      	push 	es
  1587                                  	;
  1588 000009CF B810000000              	mov	eax, KDATA
  1589 000009D4 8ED8                    	mov	ds, ax
  1590 000009D6 8EC0                    	mov	es, ax
  1591                                  	;
  1592                                  	; 25/08/2014
  1593                                  	;call	rtc_p
  1594                                  	; 23/02/2022
  1595 000009D8 FF15[2C070000]          	call	[x_rtci]
  1596                                  	;
  1597                                  	; 22/02/2015 - dsectpm.s
  1598                                  	; [ source: http://wiki.osdev.org/RTC ]
  1599                                  	; read status register C to complete procedure
  1600                                  	;(it is needed to get a next IRQ 8) 
  1601 000009DE B00C                    	mov	al, 0Ch ; 
  1602 000009E0 E670                    	out	70h, al ; select register C
  1603 000009E2 90                      	nop
  1604 000009E3 E471                    	in	al, 71h ; just throw away contents
  1605                                  	; 22/02/2015
  1606 000009E5 B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1607 000009E7 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1608                                  	;
  1609 000009E9 EBD3                    	jmp	short iiret	
  1610                                  
  1611                                  	; 22/08/2014
  1612                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1613                                  	; (INT 1Ah)
  1614                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1615                                  time_of_day:
  1616 000009EB E868010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1617 000009F0 726F                            jc      short rtc_retn 
  1618 000009F2 B000                    	mov	al, CMOS_SECONDS
  1619 000009F4 E847010000              	call	CMOS_READ
  1620 000009F9 A2[0C6C0000]            	mov	[time_seconds], al 
  1621 000009FE B002                    	mov	al, CMOS_MINUTES
  1622 00000A00 E83B010000              	call	CMOS_READ
  1623 00000A05 A2[0D6C0000]            	mov	[time_minutes], al 
  1624 00000A0A B004                    	mov	al, CMOS_HOURS
  1625 00000A0C E82F010000              	call	CMOS_READ
  1626 00000A11 A2[0E6C0000]                    mov     [time_hours], al
  1627 00000A16 B006                    	mov	al, CMOS_DAY_WEEK 
  1628 00000A18 E823010000              	call	CMOS_READ
  1629 00000A1D A2[0F6C0000]            	mov	[date_wday], al
  1630 00000A22 B007                     	mov	al, CMOS_DAY_MONTH
  1631 00000A24 E817010000              	call	CMOS_READ
  1632 00000A29 A2[106C0000]            	mov	[date_day], al
  1633 00000A2E B008                    	mov	al, CMOS_MONTH
  1634 00000A30 E80B010000              	call	CMOS_READ
  1635 00000A35 A2[116C0000]            	mov	[date_month], al
  1636 00000A3A B009                    	mov	al, CMOS_YEAR
  1637 00000A3C E8FF000000              	call	CMOS_READ
  1638 00000A41 A2[126C0000]            	mov	[date_year], al
  1639 00000A46 B032                    	mov	al, CMOS_CENTURY
  1640 00000A48 E8F3000000              	call	CMOS_READ
  1641 00000A4D A2[136C0000]            	mov	[date_century], al
  1642                                  	;
  1643 00000A52 B000                    	mov	al, CMOS_SECONDS
  1644 00000A54 E8E7000000              	call 	CMOS_READ
  1645 00000A59 3A05[0C6C0000]          	cmp	al, [time_seconds]
  1646 00000A5F 758A                    	jne	short time_of_day
  1647                                  
  1648                                  rtc_retn:
  1649 00000A61 C3                      	retn
  1650                                  
  1651                                  rtci_default:
  1652                                  	; 23/02/2022 (Temporary!)
  1653                                  	; (default real time clock handler in multitasking mode)
  1654                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1655 00000A62 FF05[546C0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1656                                  			; (not used in anywhere of kernel for now!)
  1657 00000A68 C3                      	retn
  1658                                  
  1659                                  rtc_p:	
  1660                                  	; 27/02/2022
  1661                                  	; 12/02/2022
  1662                                  	; 07/09/2014
  1663                                  	; 29/08/2014
  1664                                  	; 27/08/2014
  1665                                  	; 25/08/2014
  1666                                   	; Print Real Time Clock content
  1667                                  	;
  1668                                  	;
  1669 00000A69 E87DFFFFFF              	call	time_of_day
  1670 00000A6E 72F1                    	jc	short rtc_retn
  1671                                  	;
  1672 00000A70 3A05[D6670000]          	cmp	al, [ptime_seconds]
  1673 00000A76 74E9                            je      short rtc_retn ; 29/08/2014
  1674                                  	;
  1675 00000A78 A2[D6670000]            	mov	[ptime_seconds], al
  1676                                  	;
  1677 00000A7D A0[136C0000]            	mov	al, [date_century]
  1678 00000A82 E8EC000000              	call	bcd_to_ascii
  1679 00000A87 66A3[A3670000]          	mov	[datestr+6], ax
  1680 00000A8D A0[126C0000]            	mov	al, [date_year]
  1681 00000A92 E8DC000000              	call	bcd_to_ascii
  1682 00000A97 66A3[A5670000]          	mov	[datestr+8], ax
  1683 00000A9D A0[116C0000]            	mov	al, [date_month]
  1684 00000AA2 E8CC000000              	call	bcd_to_ascii
  1685 00000AA7 66A3[A0670000]          	mov	[datestr+3], ax
  1686 00000AAD A0[106C0000]            	mov	al, [date_day]
  1687 00000AB2 E8BC000000              	call	bcd_to_ascii
  1688 00000AB7 66A3[9D670000]          	mov	[datestr], ax
  1689                                  	;
  1690 00000ABD 0FB61D[0F6C0000]        	movzx	ebx, byte [date_wday]
  1691 00000AC4 C0E302                  	shl 	bl, 2
  1692 00000AC7 81C3[B6670000]          	add	ebx, daytmp
  1693 00000ACD 8B03                    	mov	eax, [ebx]
  1694 00000ACF A3[A8670000]            	mov	[daystr], eax
  1695                                  	;
  1696 00000AD4 A0[0E6C0000]            	mov	al, [time_hours]
  1697 00000AD9 E895000000              	call	bcd_to_ascii
  1698 00000ADE 66A3[AC670000]          	mov	[timestr], ax
  1699 00000AE4 A0[0D6C0000]            	mov	al, [time_minutes]
  1700 00000AE9 E885000000              	call	bcd_to_ascii
  1701 00000AEE 66A3[AF670000]          	mov	[timestr+3], ax
  1702 00000AF4 A0[0C6C0000]            	mov	al, [time_seconds]
  1703 00000AF9 E875000000              	call	bcd_to_ascii
  1704 00000AFE 66A3[B2670000]          	mov	[timestr+6], ax
  1705                                  	;		
  1706 00000B04 BE[8B670000]            	mov	esi, rtc_msg ; message offset
  1707                                  	; 23/02/2015
  1708 00000B09 52                      	push	edx
  1709 00000B0A 51                      	push	ecx
  1710                                  	; 07/09/2014
  1711                                  	;mov	bx, 2	; Video page 2
  1712                                  	; 27/02/2022
  1713 00000B0B 29DB                    	sub	ebx, ebx
  1714 00000B0D B307                    	mov	bl, 7	; Video page 7
  1715                                  prtmsg:
  1716 00000B0F AC                      	lodsb
  1717 00000B10 08C0                    	or	al, al
  1718 00000B12 740D                    	jz	short prtmsg_ok
  1719 00000B14 56                      	push	esi
  1720                                  	; 27/02/2022
  1721 00000B15 53                      	push	ebx
  1722                                  	;push	bx
  1723 00000B16 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1724                                  			; white (F) forecolor
  1725 00000B18 E8C1080000              	call 	write_tty
  1726                                  	;pop	bx
  1727                                  	; 27/02/2022
  1728 00000B1D 5B                      	pop	ebx
  1729 00000B1E 5E                      	pop	esi
  1730 00000B1F EBEE                    	jmp	short prtmsg
  1731                                  	;
  1732                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1733                                  	;call	printk
  1734                                  prtmsg_ok:
  1735                                  	; 07/09/2014
  1736                                  	;xor	dx, dx		; column 0, row 0
  1737                                  	; 27/02/2022
  1738 00000B21 31D2                    	xor	edx, edx
  1739 00000B23 E8C0090000              	call	set_cpos	; set cursor position to 0,0 
  1740                                  	; 23/02/2015
  1741 00000B28 59                      	pop	ecx
  1742 00000B29 5A                      	pop	edx
  1743 00000B2A C3                      	retn
  1744                                  
  1745                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1746                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1747                                  default_irq7:
  1748                                  	; 27/02/2022
  1749                                  	;push	ax
  1750 00000B2B 50                      	push	eax
  1751 00000B2C B00B                    	mov	al, 0Bh  ; In-Service register
  1752 00000B2E E620                    	out	20h, al
  1753 00000B30 EB00                            jmp short $+2
  1754 00000B32 EB00                    	jmp short $+2
  1755 00000B34 E420                    	in	al, 20h
  1756 00000B36 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1757 00000B38 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1758 00000B3A B020                            mov     al, 20h ; EOI
  1759 00000B3C E620                    	out	20h, al 
  1760                                  irq7_iret:
  1761                                  	;pop	ax
  1762                                  	; 27/02/2022
  1763 00000B3E 58                      	pop	eax
  1764 00000B3F CF                      	iretd
  1765                                  	
  1766                                  	; 22/08/2014
  1767                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1768                                  CMOS_READ:
  1769 00000B40 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1770 00000B41 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1771 00000B43 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1772 00000B44 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1773 00000B46 FA                      	cli		; DISABLE INTERRUPTS
  1774 00000B47 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1775 00000B49 90                      	nop		; I/O DELAY
  1776 00000B4A E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1777 00000B4C 6650                    	push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1778                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1779                                  		     ; ----- 10/06/85 (test4.asm)
  1780 00000B4E B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1781                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1782 00000B50 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1783 00000B52 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1784 00000B54 6658                    	pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1785 00000B56 9D                      	popf	
  1786 00000B57 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1787                                  
  1788                                  	; 22/08/2014
  1789                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1790                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1791 00000B58 51                      	push	ecx
  1792 00000B59 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1793                                  		; mov cx, 800	
  1794                                  UPD_10:
  1795 00000B5E B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1796 00000B60 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1797 00000B61 E8DAFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1798 00000B66 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1799 00000B68 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1800 00000B6A FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1801 00000B6B E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1802 00000B6D 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1803                                  		; xor ax, ax
  1804 00000B6F F9                      	stc				; SET CARRY FOR ERROR
  1805                                  UPD_90:
  1806 00000B70 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1807 00000B71 FA                      	cli				; INTERRUPTS OFF DURING SET
  1808 00000B72 C3                      	retn				; RETURN WITH CY FLAG SET
  1809                                  
  1810                                  bcd_to_ascii:
  1811                                  	; 25/08/2014
  1812                                  	; INPUT ->
  1813                                  	;	al = Packed BCD number
  1814                                  	; OUTPUT ->
  1815                                  	;	ax  = ASCII word/number
  1816                                  	;
  1817                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1818                                  	;
  1819 00000B73 D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1820                                  					; AH = AL / 10h
  1821                                  					; AL = AL MOD 10h
  1822 00000B75 660D3030                	or ax,'00'                      ; Make it ASCII based
  1823                                  
  1824 00000B79 86E0                            xchg ah, al 
  1825                                  	
  1826 00000B7B C3                      	retn	
  1827                                  	
  1828                                  %include 'keyboard.inc' ; 07/03/2015
  1829                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1830                              <1> ; Last Modification: 23/02/2022
  1831                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1832                              <1> ;
  1833                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1834                              <1> 
  1835                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1836                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1837                              <1> ; 30/06/2015
  1838                              <1> ; 11/03/2015
  1839                              <1> ; 28/02/2015
  1840                              <1> ; 25/02/2015
  1841                              <1> ; 20/02/2015
  1842                              <1> ; 18/02/2015
  1843                              <1> ; 03/12/2014
  1844                              <1> ; 07/09/2014
  1845                              <1> ; KEYBOARD INTERRUPT HANDLER
  1846                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1847                              <1> 
  1848                              <1> ;getch:
  1849                              <1> ;	; 18/02/2015
  1850                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1851                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1852                              <1> ;	; routine, later... (multi tasking ability)
  1853                              <1> ;	; 28/02/2015
  1854                              <1> ;	sti	; enable interrupts
  1855                              <1> ;	;
  1856                              <1> ;	;push	esi
  1857                              <1> ;	;push	ebx
  1858                              <1> ;	;xor	ebx, ebx
  1859                              <1> ;	;mov	bl, [ptty]  ; active_page
  1860                              <1> ;	;mov	esi, ebx
  1861                              <1> ;	;shl 	si, 1
  1862                              <1> ;	;add	esi, ttychr
  1863                              <1> ;getch_1:
  1864                              <1> ;	;mov	ax, [esi]
  1865                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1866                              <1> ;	and	ax, ax
  1867                              <1> ;	jz	short getch_2
  1868                              <1> ;	mov	word [ttychr], 0
  1869                              <1> ;	;mov	word [esi], 0
  1870                              <1> ;	;pop	ebx
  1871                              <1> ;	;pop	esi
  1872                              <1> ;	retn
  1873                              <1> ;getch_2:
  1874                              <1> ;	hlt	; not proper for multi tasking!
  1875                              <1> ;		; (temporary halt for now)
  1876                              <1> ;		; 'sleep' on tty 
  1877                              <1> ;		; will (must) be located here		
  1878                              <1> ;	nop
  1879                              <1> ;	jmp	short getch_1
  1880                              <1> 
  1881                              <1> keyb_int:
  1882                              <1> 	; 23/02/2022
  1883                              <1> 	; 30/06/2015
  1884                              <1> 	; 25/02/2015
  1885                              <1> 	; 20/02/2015
  1886                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1887                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1888                              <1> 	; 30/06/2014
  1889                              <1> 	; 10/05/2013	
  1890                              <1>       	; Retro Unix 8086 v1 feature only!
  1891                              <1> 	; 03/03/2014
  1892                              <1> 	
  1893 00000B7C 1E                  <1> 	push	ds
  1894 00000B7D 53                  <1> 	push	ebx
  1895 00000B7E 50                  <1> 	push	eax
  1896                              <1> 	;
  1897                              <1> 	; 23/02/2022
  1898 00000B7F 9C                  <1> 	pushfd
  1899 00000B80 0E                  <1> 	push	cs
  1900                              <1> 	;mov	ax, KDATA
  1901 00000B81 31C0                <1> 	xor	eax, eax
  1902 00000B83 B010                <1> 	mov	al, KDATA
  1903 00000B85 8ED8                <1> 	mov	ds, ax
  1904                              <1> 	;
  1905                              <1> 	;pushfd
  1906                              <1> 	;push	cs
  1907 00000B87 E810020000          <1> 	call	kb_int   ; int_09h
  1908                              <1> 	;
  1909 00000B8C B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1910                              <1> 	;call	getc
  1911 00000B8E E854000000          <1> 	call	int_16h  ; 30/06/2015
  1912 00000B93 744E                <1> 	jz	short keyb_int4
  1913                              <1> 	;
  1914 00000B95 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1915                              <1> 	;call	getc
  1916 00000B97 E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1917                              <1> 	;
  1918                              <1> 	; 20/02/2015
  1919 00000B9C 0FB61D[C66B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1920                              <1> 	;
  1921 00000BA3 20C0                <1> 	and 	al, al
  1922 00000BA5 751D                <1> 	jnz	short keyb_int1
  1923                              <1> 	;
  1924 00000BA7 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1925 00000BAA 7218                <1> 	jb	short keyb_int1
  1926 00000BAC 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1927 00000BAF 7713                <1> 	ja	short keyb_int1
  1928                              <1> 	;
  1929 00000BB1 88D8                <1> 	mov	al, bl
  1930 00000BB3 0468                <1> 	add	al, 68h
  1931 00000BB5 38E0                <1> 	cmp	al, ah
  1932 00000BB7 7409                <1> 	je	short keyb_int0
  1933 00000BB9 88E0                <1> 	mov	al, ah
  1934 00000BBB 2C68                <1> 	sub	al, 68h
  1935 00000BBD E83F0A0000          <1> 	call	tty_sw
  1936                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1937                              <1> keyb_int0: ; 30/06/2015
  1938                              <1> 	;xor	ax, ax
  1939                              <1> 	; 23/02/2022
  1940 00000BC2 31C0                <1> 	xor	eax, eax
  1941                              <1> keyb_int1:
  1942 00000BC4 D0E3                <1> 	shl	bl, 1
  1943 00000BC6 81C3[C86B0000]      <1> 	add	ebx, ttychr
  1944                              <1> 	;
  1945                              <1> 	;23/02/2022
  1946 00000BCC 09C0                <1> 	or	eax, eax
  1947                              <1> 	;or	ax, ax
  1948 00000BCE 7406                <1> 	jz	short keyb_int2
  1949                              <1> 	;
  1950 00000BD0 66833B00            <1> 	cmp 	word [ebx], 0
  1951 00000BD4 7703                <1>         ja      short keyb_int3 
  1952                              <1> keyb_int2:
  1953 00000BD6 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1954                              <1> 			   ; and scan code of the character
  1955                              <1> 			   ; for current tty (or last tty
  1956                              <1> 			   ; just before tty switch).
  1957                              <1> keyb_int3:
  1958 00000BD9 A0[C66B0000]        <1>         mov     al, [ptty]
  1959 00000BDE E8FF430000          <1> 	call	wakeup
  1960                              <1> 	;
  1961                              <1> keyb_int4:
  1962 00000BE3 58                  <1> 	pop	eax
  1963 00000BE4 5B                  <1> 	pop	ebx
  1964 00000BE5 1F                  <1> 	pop	ds
  1965 00000BE6 CF                  <1> 	iret
  1966                              <1> 
  1967                              <1> ; 18/02/2015
  1968                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1969                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1970                              <1> ; scancode and ascii code of the character 
  1971                              <1> ; in the tty input (ttychr) buffer. 
  1972                              <1> ; Test procedures must call 'getch' for tty input
  1973                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1974                              <1> ; due to infinite (key press) waiting loop.
  1975                              <1> ; 
  1976                              <1> ; 03/12/2014
  1977                              <1> ; 26/08/2014
  1978                              <1> ; KEYBOARD I/O
  1979                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1980                              <1> 
  1981                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1982                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1983                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1984                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1985                              <1> 
  1986                              <1> int_16h: ; 30/06/2015
  1987                              <1> ;getc:
  1988 00000BE7 9C                  <1> 	pushfd	; 28/08/2014
  1989 00000BE8 0E                  <1> 	push 	cs
  1990 00000BE9 E826000000          <1> 	call 	getc_int
  1991 00000BEE C3                  <1> 	retn
  1992                              <1> 
  1993                              <1> ; 24/12/2021
  1994                              <1> 
  1995                              <1> 	;-----	SHIFT STATUS
  1996                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  1997 00000BEF 8A25[C4650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  1998 00000BF5 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  1999                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2000                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2001 00000BF8 C0E405              <1>         shl	ah, 5
  2002 00000BFB A0[C4650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2003 00000C00 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2004 00000C02 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2005 00000C04 A0[C6650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2006 00000C09 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2007 00000C0B 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2008                              <1> _K3:
  2009 00000C0D A0[C3650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2010 00000C12 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2011                              <1> 
  2012                              <1> getc_int:
  2013                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2014                              <1> 	; 28/02/2015
  2015                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2016                              <1> 	;	      instead of pc-at bios - 1985-)
  2017                              <1> 	; 28/08/2014 (_k1d)
  2018                              <1> 	; 30/06/2014
  2019                              <1> 	; 03/03/2014
  2020                              <1> 	; 28/02/2014
  2021                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2022                              <1> 	; rombios source code (21/04/1986)
  2023                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2024                              <1> 	;
  2025                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2026                              <1> 	;
  2027                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2028                              <1> 	; KEYBOARD I/O								      :
  2029                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2030                              <1> 	; INPUT									      :
  2031                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2032                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2033                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2034                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2035                              <1> 	;-----------------------------------------------------------------------------:
  2036                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2037                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2038                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2039                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2040                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2041                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2042                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2043                              <1> 	;-----------------------------------------------------------------------------:	
  2044                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2045                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2046                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2047                              <1> 	;-----------------------------------------------------------------------------:	
  2048                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2049                              <1> 	;	      (AL) = 05H                                                      :
  2050                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2051                              <1> 	;		       							      :
  2052                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2053                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2054                              <1> 	;                     --------------------------------------------            :
  2055                              <1> 	;			00H        30.0        10H        7.5                 :
  2056                              <1> 	;			01H        26.7        11H        6.7                 :
  2057                              <1> 	;			02H        24.0        12H        6.0                 :
  2058                              <1> 	;			03H        21.8        13H        5.5                 :
  2059                              <1> 	;			04H        20.0        14H        5.0                 :
  2060                              <1> 	;			05H        18.5        15H        4.6                 :
  2061                              <1> 	;			06H        17.1        16H        4.3                 :
  2062                              <1> 	;			07H        16.0        17H        4.0                 :
  2063                              <1> 	;			08H        15.0        18H        3.7                 :
  2064                              <1> 	;			09H        13.3        19H        3.3                 :
  2065                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2066                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2067                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2068                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2069                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2070                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2071                              <1> 	;									      :
  2072                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2073                              <1> 	;		       							      :
  2074                              <1> 	;                     REGISTER     DELAY                                      :
  2075                              <1> 	;                      VALUE       VALUE                                      :
  2076                              <1> 	;                     ------------------                                      :
  2077                              <1> 	;			00H        250 ms                                     :
  2078                              <1> 	;			01H        500 ms                                     :
  2079                              <1> 	;			02H        750 ms                                     :
  2080                              <1> 	;			03H       1000 ms                                     :
  2081                              <1> 	;-----------------------------------------------------------------------------:
  2082                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2083                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2084                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2085                              <1> 	;		           (CH) = SCAN CODE                                   :
  2086                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2087                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2088                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2089                              <1> 	;-----------------------------------------------------------------------------:		
  2090                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2091                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2092                              <1> 	;-----------------------------------------------------------------------------:
  2093                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2094                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2095                              <1> 	;-----------------------------------------------------------------------------:	
  2096                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2097                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2098                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2099                              <1> 	; OUTPUT					                              :
  2100                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2101                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2102                              <1> 	;------------------------------------------------------------------------------
  2103                              <1> 	
  2104 00000C14 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2105 00000C15 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2106 00000C16 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2107                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2108 00000C17 66BB1000            <1>         mov     bx, KDATA 
  2109 00000C1B 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2110 00000C1D 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2111 00000C1F 742D                <1> 	jz	short _K1		; ASCII_READ
  2112 00000C21 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2113 00000C23 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2114 00000C25 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2115 00000C27 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2116 00000C29 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2117 00000C2B 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2118 00000C2D 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2119 00000C30 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2120                              <1> _KIO1:	
  2121 00000C32 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2122 00000C35 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2123 00000C37 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2124 00000C39 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2125 00000C3B FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2126 00000C3D 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2127                              <1> _KIO_EXIT:
  2128                              <1> 	;pop	ecx			; RECOVER REGISTER
  2129 00000C3F 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2130 00000C40 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2131 00000C41 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2132                              <1> 
  2133                              <1> 	;-----	ASCII CHARACTER
  2134                              <1> _K1E:	
  2135 00000C42 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2136 00000C47 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2137 00000C4C EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2138                              <1> _K1:	
  2139 00000C4E E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2140 00000C53 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2141 00000C58 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2142                              <1> _K1A:
  2143 00000C5A EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2144                              <1> 
  2145                              <1> 	;-----	ASCII STATUS
  2146                              <1> _K2E:	
  2147 00000C5C E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2148 00000C61 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2149 00000C63 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2150 00000C64 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2151 00000C69 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2152                              <1> _K2:	
  2153 00000C6B E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2154 00000C70 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2155 00000C72 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2156 00000C73 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2157 00000C78 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2158 00000C7A 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2159 00000C7B E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2160 00000C80 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2161                              <1> _K2A:
  2162 00000C82 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2163                              <1> _K2B:
  2164                              <1> 	;pop	ecx			; RECOVER REGISTER
  2165 00000C83 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2166 00000C84 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2167 00000C85 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2168                              <1> 
  2169                              <1> ; 24/12/2021
  2170                              <1> ;	;-----	SHIFT STATUS
  2171                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2172                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2173                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2174                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2175                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2176                              <1> ;       shl	ah, 5
  2177                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2178                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2179                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2180                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2181                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2182                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2183                              <1> ;_K3:
  2184                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2185                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2186                              <1> 
  2187                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2188                              <1> _K300:
  2189 00000C88 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2190 00000C8A 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2191 00000C8C F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2192 00000C8F 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2193 00000C91 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2194 00000C94 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2195 00000C96 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2196 00000C98 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2197                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2198                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2199 00000C9D C0E705              <1> 	shl	bh, 5
  2200 00000CA0 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2201 00000CA2 08F8                <1> 	or	al, bh			; AND DELAY
  2202 00000CA4 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2203 00000CA9 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2204                              <1> 
  2205                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2206                              <1> _K500:
  2207 00000CAB 56                  <1> 	push	esi			; SAVE SI (esi)
  2208 00000CAC FA                  <1> 	cli				; 
  2209 00000CAD 8B1D[D4650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2210 00000CB3 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2211 00000CB5 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2212 00000CBA 3B1D[D0650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2213 00000CC0 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2214 00000CC2 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2215 00000CC5 891D[D4650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2216 00000CCB 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2217 00000CCD EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2218                              <1> _K502:
  2219 00000CCF B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2220                              <1> _K504:
  2221 00000CD1 FB                  <1> 	sti				
  2222 00000CD2 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2223 00000CD3 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2224                              <1> 
  2225                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2226                              <1> _K1S:
  2227 00000CD8 FA                  <1> 	cli	; 03/12/2014
  2228 00000CD9 8B1D[D0650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2229 00000CDF 3B1D[D4650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2230                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2231 00000CE5 750F                <1> 	jne	short _k1x ; 03/12/2014
  2232                              <1> 	;
  2233                              <1> 	; 03/12/2014
  2234                              <1> 	; 28/08/2014
  2235                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2236                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2237                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2238                              <1> _K1T:                                   ; ASCII READ
  2239 00000CE7 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2240 00000CE8 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2241                              <1> _K1U:	
  2242 00000CE9 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2243 00000CEA 8B1D[D0650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2244 00000CF0 3B1D[D4650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2245                              <1> _k1x:
  2246 00000CF6 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2247 00000CF7 9C                  <1> 	pushf				; SAVE FLAGS
  2248 00000CF8 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2249 00000CFD 8A1D[C5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2250 00000D03 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2251 00000D05 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2252 00000D08 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2253 00000D0A E86E060000          <1> 	call	SND_LED1
  2254 00000D0F FA                  <1> 	cli				; DISABLE INTERRUPTS
  2255                              <1> _K1V:
  2256 00000D10 9D                  <1> 	popf				; RESTORE FLAGS
  2257 00000D11 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2258 00000D12 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2259                              <1> 	;
  2260 00000D14 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2261 00000D17 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2262 00000D1C 891D[D0650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2263 00000D22 C3                  <1> 	retn				; RETURN
  2264                              <1> 
  2265                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2266                              <1> _K2S:
  2267 00000D23 FA                  <1> 	cli				; INTERRUPTS OFF
  2268 00000D24 8B1D[D0650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2269 00000D2A 3B1D[D4650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2270 00000D30 668B03              <1> 	mov	ax, [ebx]
  2271 00000D33 9C                  <1> 	pushf				; SAVE FLAGS
  2272                              <1> 	;push	ax			; SAVE CODE
  2273                              <1> 	; 24/12/2021
  2274 00000D34 50                  <1> 	push	eax
  2275 00000D35 E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2276 00000D3A 8A1D[C5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2277 00000D40 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2278 00000D42 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2279 00000D45 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2280 00000D47 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2281                              <1> _K2T:
  2282                              <1> 	;pop	ax			; RESTORE CODE
  2283                              <1> 	; 24/12/2021
  2284 00000D4C 58                  <1> 	pop	eax
  2285 00000D4D 9D                  <1> 	popf				; RESTORE FLAGS
  2286 00000D4E FB                  <1> 	sti				; INTERRUPTS BACK ON
  2287 00000D4F C3                  <1> 	retn				; RETURN
  2288                              <1> 
  2289                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2290                              <1> _KIO_E_XLAT:
  2291 00000D50 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2292 00000D52 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2293 00000D54 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2294 00000D56 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2295 00000D58 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2296                              <1> _KIO_E_RET:				
  2297 00000D5A C3                  <1> 	retn				; GO BACK
  2298                              <1> 
  2299                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2300                              <1> _KIO_S_XLAT:
  2301 00000D5B 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2302 00000D5E 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2303 00000D60 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2304 00000D62 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2305 00000D64 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2306 00000D66 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2307 00000D68 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2308                              <1> _kio_ret: ; 03/12/2014
  2309 00000D6A F8                  <1> 	clc
  2310 00000D6B C3                  <1> 	retn
  2311                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2312                              <1> _KIO_S1:				
  2313 00000D6C B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2314                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2315 00000D6E C3                  <1> 	retn
  2316                              <1> _KIO_S2:		
  2317 00000D6F 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2318 00000D72 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2319 00000D74 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2320 00000D76 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2321 00000D78 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2322 00000D7A 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2323 00000D7C EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2324                              <1> _KIO_S3:
  2325 00000D7E 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2326                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2327 00000D80 75E8                <1> 	jne	short _kio_ret
  2328 00000D82 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2329 00000D84 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2330 00000D86 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2331                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2332                              <1> _KIO_USE:
  2333                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2334 00000D88 C3                  <1> 	retn				; RETURN	
  2335                              <1> _KIO_DIS:
  2336 00000D89 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2337 00000D8A C3                  <1> 	retn				; RETURN
  2338                              <1> 
  2339                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2340                              <1> _K4:    
  2341 00000D8B 43                  <1> 	inc     ebx
  2342 00000D8C 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2343 00000D8D 3B1D[CC650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2344                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2345 00000D93 7206                <1> 	jb	short _K5
  2346 00000D95 8B1D[C8650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2347                              <1> _K5:
  2348 00000D9B C3                  <1> 	retn
  2349                              <1> 
  2350                              <1> ; 20/02/2015
  2351                              <1> ; 05/12/2014
  2352                              <1> ; 26/08/2014
  2353                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2354                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2355                              <1> ;
  2356                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2357                              <1> ; rombios source code (06/10/1985)
  2358                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2359                              <1> 
  2360                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2361                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2362                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2363                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2364                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2365                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2366                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2367                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2368                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2369                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2370                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2371                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2372                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2373                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2374                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2375                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2376                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2377                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2378                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2379                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2380                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2381                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2382                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2383                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2384                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2385                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2386                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2387                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2388                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2389                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2390                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2391                              <1> F11_M		equ	87		; F11 KEY MAKE
  2392                              <1> F12_M		equ	88		; F12 KEY MAKE
  2393                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2394                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2395                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2396                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2397                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2398                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2399                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2400                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2401                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2402                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2403                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2404                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2405                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2406                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2407                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2408                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2409                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2410                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2411                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2412                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2413                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2414                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2415                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2416                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2417                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2418                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2419                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2420                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2421                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2422                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2423                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2424                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2425                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2426                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2427                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2428                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2429                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2430                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2431                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2432                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2433                              <1> ;
  2434                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2435                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2436                              <1> INTA00		equ	020h		; 8259 PORT
  2437                              <1> 
  2438                              <1> 
  2439                              <1> kb_int:
  2440                              <1> 
  2441                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2442                              <1> ; 17/10/2015 ('ctrlbrk') 
  2443                              <1> ; 05/12/2014
  2444                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2445                              <1> 	;	      instead of pc-at bios - 1985-)
  2446                              <1> ; 26/08/2014
  2447                              <1> ;
  2448                              <1> ; 03/06/86  KEYBOARD BIOS
  2449                              <1> ;
  2450                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2451                              <1> ;										;
  2452                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2453                              <1> ;										;
  2454                              <1> ;--------------------------------------------------------------------------------
  2455                              <1> 
  2456                              <1> KB_INT_1:
  2457 00000D9C FB                  <1> 	sti				; ENABLE INTERRUPTS
  2458                              <1> 	;push	ebp
  2459 00000D9D 50                  <1> 	push	eax
  2460 00000D9E 53                  <1> 	push	ebx
  2461 00000D9F 51                  <1> 	push	ecx
  2462 00000DA0 52                  <1> 	push	edx
  2463 00000DA1 56                  <1> 	push	esi
  2464 00000DA2 57                  <1> 	push	edi
  2465 00000DA3 1E                  <1> 	push	ds
  2466 00000DA4 06                  <1> 	push	es
  2467 00000DA5 FC                  <1> 	cld				; FORWARD DIRECTION
  2468 00000DA6 66B81000            <1> 	mov	ax, KDATA
  2469 00000DAA 8ED8                <1> 	mov	ds, ax
  2470 00000DAC 8EC0                <1> 	mov	es, ax
  2471                              <1> 	;
  2472                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2473 00000DAE B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2474 00000DB0 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2475 00000DB5 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2476 00000DB6 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2477                              <1> KB_INT_01:
  2478 00000DBB E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2479 00000DBD A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2480 00000DBF E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2481                              <1> 	;
  2482                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2483 00000DC1 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2484                              <1> 	;
  2485                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2486                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2487                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2488                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2489                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2490                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2491                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2492                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2493                              <1> 	;
  2494                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2495                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2496 00000DC3 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2497 00000DC4 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2498 00000DC6 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2499                              <1> 	;
  2500                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2501 00000DC8 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2502 00000DCA 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2503                              <1> 	;
  2504                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2505 00000DCC FA                  <1> 	cli				; DISABLE INTERRUPTS
  2506 00000DCD 800D[C5650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2507 00000DD4 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2508                              <1> 	;
  2509                              <1> 	;-----	RESEND THE LAST BYTE
  2510                              <1> KB_INT_4:
  2511 00000DD9 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2512 00000DDA 800D[C5650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2513 00000DE1 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2514                              <1> 	;
  2515                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2516                              <1> KB_INT_2:
  2517                              <1> 	;push 	ax			; SAVE DATA IN
  2518                              <1> 	; 24/12/2021
  2519 00000DE6 50                  <1> 	push	eax
  2520 00000DE7 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2521 00000DEC 8A1D[C5650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2522 00000DF2 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2523 00000DF4 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2524 00000DF7 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2525 00000DF9 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2526                              <1> UP0:
  2527                              <1> 	;pop	ax			; RESTORE DATA IN
  2528                              <1> 	; 24/12/2021
  2529 00000DFE 58                  <1> 	pop	eax
  2530                              <1> ;------------------------------------------------------------------------
  2531                              <1> ;	START OF KEY PROCESSING						;
  2532                              <1> ;------------------------------------------------------------------------
  2533 00000DFF 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2534                              <1> 	;
  2535                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2536 00000E01 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2537                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2538                              <1> 	; 24/12/2021
  2539 00000E03 7505                <1> 	jne	short K16
  2540 00000E05 E9ED040000          <1> 	jmp	K62
  2541                              <1> K16:	
  2542 00000E0A 8A3D[C6650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2543                              <1> 	;
  2544                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2545 00000E10 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2546 00000E13 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2547 00000E15 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2548 00000E17 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2549 00000E19 7507                <1> 	jne	short RST_RD_ID
  2550 00000E1B 800D[C6650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2551                              <1> RST_RD_ID:
  2552 00000E22 8025[C6650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2553 00000E29 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2554                              <1> 	; 24/12/2021
  2555                              <1> 	;jmp	K26
  2556                              <1> 	;
  2557                              <1> TST_ID_2:
  2558 00000E2B 8025[C6650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2559 00000E32 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2560 00000E34 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2561 00000E36 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2562 00000E38 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2563                              <1> 	; 24/12/2021
  2564                              <1> 	;jne	K26
  2565                              <1> 	;
  2566                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2567 00000E3A F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2568 00000E3D 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2569 00000E3F 800D[C3650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2570 00000E46 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2571                              <1> KX_BIT:
  2572 00000E4B 800D[C6650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2573 00000E52 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2574                              <1> 	;
  2575                              <1> NOT_ID:
  2576 00000E57 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2577 00000E59 750E                <1> 	jne	short TEST_E1
  2578 00000E5B 800D[C6650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2579 00000E62 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2580                              <1> 	; 24/12/2021
  2581 00000E64 E9DA010000          <1> 	jmp	K26A	
  2582                              <1> TEST_E1:	
  2583 00000E69 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2584 00000E6B 750C                <1> 	jne	short NOT_HC
  2585 00000E6D 800D[C6650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2586 00000E74 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2587                              <1> 	;
  2588                              <1> NOT_HC:
  2589 00000E79 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2590 00000E7B F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2591 00000E7E 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2592                              <1> 	;
  2593 00000E80 BF[AE640000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2594 00000E85 AE                  <1> 	scasb
  2595                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2596                              <1> 	; 24/12/2021
  2597 00000E86 7458                <1> 	je	short K16B
  2598 00000E88 AE                  <1> 	scasb
  2599 00000E89 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2600 00000E8B EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2601                              <1> 	; 24/12/2021
  2602                              <1> 	;jmp	K26
  2603                              <1> 	;
  2604                              <1> NOT_LC_E0:
  2605 00000E8D F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2606 00000E90 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2607 00000E92 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2608 00000E97 BF[AC640000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2609 00000E9C F2AE                <1> 	repne	scasb			; CHECK IT
  2610 00000E9E 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2611                              <1> 	; 24/12/2021
  2612                              <1> 	;je	K26A			
  2613                              <1> 	;
  2614 00000EA0 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2615 00000EA2 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2616                              <1> 	; 24/12/2021
  2617                              <1> 	;jne	K26
  2618 00000EA4 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2619 00000EA7 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2620                              <1> 	; 24/12/2021
  2621                              <1> 	;jnz	K26
  2622                              <1>         ; 20/02/2015 
  2623 00000EA9 F605[C4650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2624 00000EB0 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2625                              <1> 	; 24/12/2021
  2626                              <1> 	;jnz	K26
  2627 00000EB2 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2628                              <1> 	;
  2629                              <1> 	;-----	TEST FOR SYSTEM KEY
  2630                              <1> T_SYS_KEY:
  2631 00000EB7 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2632 00000EB9 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2633                              <1> 	;
  2634 00000EBB F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2635 00000EBE 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2636                              <1> 	;
  2637 00000EC0 F605[C4650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2638 00000EC7 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2639                              <1> 	;jnz	K26			
  2640                              <1> 	;
  2641 00000EC9 800D[C4650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2642 00000ED0 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2643 00000ED2 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2644                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2645 00000ED4 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2646 00000ED6 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2647                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2648                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2649                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2650                              <1> 	;INT	15H			; USER INTERRUPT	
  2651 00000EDB E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2652                              <1> 	;
  2653 00000EE0 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2654                              <1> 	;
  2655                              <1> K16C:
  2656 00000EE5 8025[C4650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2657 00000EEC B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2658 00000EEE E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2659                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2660                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2661                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2662                              <1> 	;
  2663                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2664                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2665                              <1> 	;INT	15H			; USER INTERRUPT
  2666                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2667                              <1> 	;
  2668 00000EF0 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2669                              <1> 	;
  2670                              <1> 	;-----	TEST FOR SHIFT KEYS
  2671                              <1> K16A:
  2672 00000EF5 8A1D[C3650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2673 00000EFB BF[A8640000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2674 00000F00 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2675 00000F05 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2676 00000F07 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2677                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2678                              <1> 	; 24/12/2021
  2679 00000F09 7405                <1> 	je	short K17
  2680 00000F0B E914010000          <1> 	jmp	K25
  2681                              <1> 	;
  2682                              <1> 	;------	SHIFT KEY FOUND
  2683                              <1> K17:
  2684 00000F10 81EF[A9640000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2685 00000F16 8AA7[B0640000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2686 00000F1C B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2687 00000F1E A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2688                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2689                              <1> 	; 24/12/2021
  2690 00000F20 7405                <1> 	jz	short K17C
  2691 00000F22 E999000000          <1> 	jmp	K23
  2692                              <1> 	;
  2693                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2694                              <1> K17C:
  2695 00000F27 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2696 00000F2A 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2697                              <1> 	;
  2698                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2699 00000F2C 0825[C3650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2700 00000F32 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2701 00000F34 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2702                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2703                              <1> 	; 24/12/2021
  2704 00000F36 E901010000          <1> 	jmp	K26
  2705                              <1> K17D:
  2706 00000F3B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2707 00000F3E 740B                <1> 	jz 	short K17E		; NO, JUMP
  2708 00000F40 0825[C6650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2709 00000F46 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2710                              <1> K17E:
  2711 00000F4B D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2712 00000F4D 0825[C4650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2713 00000F53 E9E4000000          <1> 	jmp	K26
  2714                              <1> 	;
  2715                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2716                              <1> K18:					; SHIFT-TOGGLE
  2717 00000F58 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2718 00000F5B 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2719                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2720                              <1> 	; 24/12/2021
  2721 00000F5D E9C2000000          <1> 	jmp	K25
  2722                              <1> K18A:
  2723 00000F62 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2724 00000F64 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2725 00000F66 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2726 00000F69 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2727                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2728                              <1> 	; 24/12/2021
  2729 00000F6B E9B4000000          <1> 	jmp	K25
  2730                              <1> K18B:
  2731 00000F70 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2732 00000F73 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2733                              <1> K19:	
  2734 00000F75 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2735 00000F78 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2736 00000F7A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2737 00000F7D 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2738                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2739 00000F7F 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2740 00000F81 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2741                              <1> K21:					; MIGHT BE NUMERIC
  2742 00000F86 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2743 00000F89 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2744                              <1> 	;
  2745                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2746 00000F8B 8425[C4650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2747                              <1> 	;jnz	K26
  2748                              <1> 	; 24/12/2021
  2749 00000F91 7405                <1> 	jz	short K22A
  2750 00000F93 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2751                              <1> K22A:
  2752 00000F98 0825[C4650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2753 00000F9E 3025[C3650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2754                              <1> 	;
  2755                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2756 00000FA4 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2757 00000FA7 7407                <1> 	jz	short K22B		; GO IF NOT
  2758                              <1> 	;
  2759                              <1> 	; 24/12/2021
  2760                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2761 00000FA9 50                  <1> 	push	eax
  2762 00000FAA E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2763                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2764 00000FAF 58                  <1> 	pop	eax
  2765                              <1> K22B:
  2766 00000FB0 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2767                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2768                              <1> 	; 24/12/2021
  2769 00000FB2 7405                <1> 	je	short K22C
  2770 00000FB4 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2771                              <1> K22C:
  2772 00000FB9 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2773 00000FBB E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2774                              <1> 	;
  2775                              <1> 	;-----	BREAK SHIFT FOUND
  2776                              <1> K23:					; BREAK-SHIFT-FOUND
  2777 00000FC0 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2778 00000FC3 F6D4                <1> 	not	ah			; INVERT MASK
  2779 00000FC5 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2780 00000FC7 2025[C3650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2781 00000FCD 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2782 00000FD0 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2783                              <1> 	;
  2784 00000FD2 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2785 00000FD5 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2786 00000FD7 2025[C6650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2787 00000FDD EB08                <1> 	jmp	short K23B		; CONTINUE
  2788                              <1> K23A:
  2789 00000FDF D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2790 00000FE1 2025[C4650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2791                              <1> K23B:
  2792 00000FE7 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2793 00000FE9 A0[C6650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2794 00000FEE D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2795 00000FF0 0A05[C4650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2796 00000FF6 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2797 00000FF8 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2798 00000FFA 0805[C3650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2799 00001000 88E0                <1> 	mov	al, ah
  2800                              <1> K23D:
  2801 00001002 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2802 00001004 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2803                              <1> 	;	
  2804                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2805 00001006 A0[C7650000]        <1> 	mov	al, [ALT_INPUT]
  2806 0000100B B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2807 0000100D 8825[C7650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2808 00001013 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2809 00001015 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2810 00001017 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2811                              <1> 	;
  2812                              <1> K24:					; BREAK-TOGGLE
  2813 0000101C 2025[C4650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2814 00001022 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2815                              <1> 	;
  2816                              <1> 	;-----	TEST FOR HOLD STATE
  2817                              <1> 					; AL, AH = SCAN CODE
  2818                              <1> K25:					; NO-SHIFT-FOUND
  2819 00001024 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2820 00001026 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2821 00001028 F605[C4650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2822 0000102F 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2823 00001031 3C45                <1> 	cmp	al, NUM_KEY
  2824 00001033 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2825 00001035 8025[C4650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2826                              <1> 	;
  2827                              <1> K26:
  2828 0000103C 8025[C6650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2829                              <1> K26A:					; INTERRUPT-RETURN
  2830 00001043 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2831 00001044 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2832 00001046 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2833                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2834 00001048 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2835 0000104A E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2836                              <1> K27A:
  2837 0000104F FA                  <1> 	cli				; DISABLE INTERRUPTS
  2838 00001050 07                  <1> 	pop	es			; RESTORE REGISTERS
  2839 00001051 1F                  <1> 	pop	ds
  2840 00001052 5F                  <1> 	pop	edi
  2841 00001053 5E                  <1> 	pop	esi
  2842 00001054 5A                  <1> 	pop	edx
  2843 00001055 59                  <1> 	pop	ecx
  2844 00001056 5B                  <1> 	pop	ebx
  2845 00001057 58                  <1> 	pop	eax
  2846                              <1> 	;pop	ebp
  2847 00001058 CF                  <1> 	iret				; RETURN
  2848                              <1> 
  2849                              <1> 	;-----	NOT IN	HOLD STATE
  2850                              <1> K28:					; NO-HOLD-STATE
  2851 00001059 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2852 0000105B 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2853                              <1> 	;
  2854 0000105D F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2855 00001060 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2856                              <1>         ; 24/12/2021
  2857                              <1> 	;jz      K38
  2858                              <1> 	;
  2859 00001062 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2860 00001065 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2861                              <1> 	; 28/02/2015
  2862 00001067 F605[C4650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2863 0000106E 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2864                              <1> 	; 24/12/2021
  2865                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2866                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2867 00001070 E9D1000000          <1> K28A:	jmp	K38
  2868                              <1> 	;
  2869                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2870                              <1> K29:					; TEST-RESET
  2871 00001075 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2872 00001078 740B                <1> 	jz	short K31		; NO_RESET
  2873 0000107A 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2874 0000107C 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2875                              <1> 	;
  2876                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2877                              <1>  	; 26/08/2014
  2878                              <1> cpu_reset:
  2879                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2880                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2881 0000107E B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2882 00001080 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2883                              <1> khere:
  2884 00001082 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2885 00001083 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2886                              <1> 
  2887                              <1> 	;
  2888                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2889                              <1> K31:					; NO-RESET
  2890 00001085 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2891 00001087 7507                <1> 	jne	short K311		; NOT THERE
  2892 00001089 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2893 0000108B E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2894                              <1> K311:
  2895 00001090 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2896 00001092 7509                <1> 	jne	short K312		; NOT THERE
  2897 00001094 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2898 00001098 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2899                              <1> K312:
  2900 0000109D 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2901 0000109F 7471                <1>         je	short K37B              ; GO PROCESS
  2902 000010A1 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2903 000010A3 746D                <1>         je	short K37B              ; GO PROCESS
  2904                              <1> 	;
  2905                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2906                              <1> K32:					; ALT-KEY-PAD
  2907 000010A5 BF[84640000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2908 000010AA B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2909 000010AF F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2910 000010B1 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2911 000010B3 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2912                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2913                              <1> 	; 24/12/2021
  2914 000010B6 751C                <1> 	jnz	short K32B
  2915 000010B8 81EF[85640000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2916 000010BE A0[C7650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2917 000010C3 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2918 000010C5 F6E4                <1> 	mul	ah
  2919 000010C7 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2920 000010CA A2[C7650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2921                              <1> K32A:
  2922 000010CF E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2923                              <1> K32B:
  2924                              <1> 	; 24/12/2021
  2925 000010D4 EB6A                <1> 	jmp	K37C
  2926                              <1> 	;
  2927                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2928                              <1> K33:					; NO-ALT-KEYPAD
  2929 000010D6 C605[C7650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2930 000010DD B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2931 000010E2 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2932 000010E4 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2933                              <1> 	;
  2934                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2935                              <1> K34:					; ALT-TOP-ROW
  2936 000010E6 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2937 000010E8 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2938 000010EA 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2939 000010EC 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2940 000010EE 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2941 000010F1 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2942                              <1> 	;
  2943                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2944                              <1> K35:					; ALT-FUNCTION
  2945 000010F3 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2946 000010F5 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2947 000010F7 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2948 000010F9 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2949 000010FB 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2950 000010FE EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2951                              <1> K35A:
  2952 00001100 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2953 00001103 7425                <1> 	jz	short K37		; NO, JUMP
  2954 00001105 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2955 00001107 7510                <1>         jne     short K35B              ; NOT THERE
  2956 00001109 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2957 0000110D E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2958                              <1> K37B:
  2959 00001112 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2960 00001114 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2961                              <1> K35B:
  2962 00001119 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2963 0000111B 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2964 0000111D 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2965 0000111F 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2966                              <1>         ; 24/12/2021
  2967                              <1> 	;jne	K26
  2968 00001121 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2969 00001125 E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2970                              <1> K37:
  2971 0000112A 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2972 0000112C 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2973 0000112E 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2974                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2975 00001130 0F8706FFFFFF        <1>         ja      K26
  2976 00001136 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2977                              <1> K37A:
  2978 00001139 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2979 0000113B E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2980                              <1> K37C:
  2981 00001140 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2982 00001142 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2983 00001144 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2984                              <1> 	;
  2985                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2986                              <1> K38:					; NOT-ALT-SHIFT
  2987                              <1> 					; BL STILL HAS SHIFT FLAGS
  2988 00001146 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2989 00001149 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2990                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2991                              <1> 	; 24/12/2021
  2992 0000114B E9AB000000          <1> 	jmp	K44
  2993                              <1> 	;
  2994                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  2995                              <1> 	;-----	TEST FOR BREAK
  2996                              <1> K38A:
  2997 00001150 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  2998 00001152 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  2999 00001154 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3000 00001157 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3001 00001159 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3002 0000115C 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3003                              <1> K38B:
  3004 0000115E 8B1D[D0650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3005 00001164 891D[D4650000]      <1> 	mov	[BUFFER_TAIL], ebx
  3006 0000116A C605[C2650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3007                              <1> 	;
  3008                              <1> 	;-----	ENABLE KEYBOARD
  3009 00001171 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3010 00001173 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3011                              <1> 	;
  3012                              <1> 	; CTRL+BREAK code here !!!
  3013                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3014                              <1> 	; 17/10/2015	
  3015 00001178 E857220000          <1> 	call	ctrlbrk ; control+break subroutine
  3016                              <1> 	;
  3017                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3018                              <1> 	; 24/12/2021
  3019 0000117D 29C0                <1> 	sub	eax, eax
  3020 0000117F E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3021                              <1> 	;
  3022                              <1> 	;-----	TEST FOR PAUSE
  3023                              <1> K39:					; NO_BREAK
  3024 00001184 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3025 00001187 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3026 00001189 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3027 0000118B 7533                <1> 	jne	short K41		; NO-PAUSE
  3028                              <1> K39P:
  3029 0000118D 800D[C4650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3030                              <1> 	;
  3031                              <1> 	;-----	ENABLE KEYBOARD
  3032 00001194 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3033 00001196 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3034                              <1> K39A:
  3035 0000119B B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3036 0000119D E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3037                              <1> 	;
  3038                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3039 0000119F 803D[C0650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3040 000011A6 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3041 000011A8 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3042 000011AC A0[C1650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3043 000011B1 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3044                              <1> 	;
  3045                              <1> K40:					; PAUSE-LOOP
  3046 000011B2 F605[C4650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3047 000011B9 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3048                              <1> 	;
  3049 000011BB E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3050                              <1>         ;
  3051                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3052                              <1> K41:					; NO-PAUSE
  3053 000011C0 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3054 000011C2 7513                <1> 	jne	short K42		; NOT-KEY-55
  3055 000011C4 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3056 000011C7 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3057 000011C9 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3058 000011CC 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3059                              <1> K41A:	
  3060 000011CE 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3061 000011D2 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3062                              <1> 	;
  3063                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3064                              <1> K42:					; NOT-KEY-55
  3065 000011D7 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3066 000011D9 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3067 000011DB 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3068 000011DD 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3069 000011DF F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3070 000011E2 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3071 000011E4 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3072 000011E8 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3073                              <1> K42A:
  3074                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3075 000011ED 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3076                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3077                              <1> 	;;jb	K56 ; 20/02/2015
  3078                              <1> 	;;jmp	K64 ; 20/02/2015
  3079                              <1> K42B:
  3080 000011EF BB[B8640000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3081                              <1> 	;;jmp	K64
  3082                              <1> 	;jb	K56 ;; 20/02/2015	
  3083                              <1> 	; 24/12/2021
  3084 000011F4 7267                <1> 	jb	short K45F
  3085 000011F6 E9B9000000          <1> 	jmp	K64	
  3086                              <1>         ;
  3087                              <1> 	;-----	NOT IN CONTROL SHIFT
  3088                              <1> K44:					; NOT-CTL-SHIFT
  3089 000011FB 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3090 000011FD 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3091 000011FF F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3092 00001202 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3093 00001204 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3094 00001207 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3095 00001209 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3096                              <1> K44A:
  3097 0000120B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3098 0000120E 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3099                              <1> 	;
  3100                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3101                              <1> K44B:
  3102 00001210 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3103 00001212 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3104 00001217 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3105 00001219 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3106                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3107                              <1> 	;PUSH 	BP			; SAVE POINTER
  3108                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3109                              <1> 	;POP	BP			; RESTORE POINTER
  3110 0000121B 8025[C6650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3111 00001222 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3112                              <1> 	;
  3113                              <1> 	;-----	HANDLE IN-CORE KEYS
  3114                              <1> K45:					; NOT-PRINT-SCREEN
  3115 00001227 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3116 00001229 7734                <1> 	ja	short K46		; JUMP IF NOT
  3117 0000122B 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3118 0000122D 7505                <1> 	jne	short K45A		; NO, JUMP
  3119 0000122F F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3120 00001232 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3121                              <1> K45A:
  3122 00001234 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3123 00001239 BF[8E640000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3124 0000123E F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3125                              <1> 		; 20/02/2015
  3126 00001240 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3127                              <1> 	;
  3128 00001242 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3129 00001245 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3130                              <1> K45B:
  3131 00001247 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3132 0000124A 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3133                              <1> 					; NO, LOWERCASE
  3134                              <1> K45C:
  3135 0000124C BB[10650000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3136 00001251 EB51                <1> 	jmp	short K56	
  3137                              <1> K45D:					; ALMOST-CAPS-STATE
  3138 00001253 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3139 00001256 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3140                              <1> K45E:
  3141 00001258 BB[68650000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3142 0000125D EB45                <1> K45F:	jmp	short K56
  3143                              <1> 	;
  3144                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3145                              <1> K46:					; NOT IN-CORE AREA
  3146 0000125F 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3147                              <1> 	;ja	short K47		; JUMP IF NOT
  3148                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3149 00001261 7635                <1> 	jna	short K53		
  3150                              <1> 	;
  3151                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3152                              <1> K47:					; NOT F1 - F10
  3153 00001263 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3154 00001265 772D                <1> 	ja	short K52		; JUMP IF NOT
  3155                              <1> 	;
  3156                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3157                              <1> K48:
  3158 00001267 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3159 00001269 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3160 0000126B 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3161 0000126D 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3162 0000126F F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3163 00001272 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3164                              <1> 	;		
  3165 00001274 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3166 00001277 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3167 00001279 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3168                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3169 0000127C 75DA                <1> 	jnz	short K45E
  3170                              <1> 	;
  3171                              <1> 	;-----	BASE CASE FOR KEYPAD
  3172                              <1> K49:					
  3173 0000127E 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3174 00001280 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3175 00001282 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3176 00001284 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3177                              <1> K49A:
  3178 00001286 BB[10650000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3179 0000128B EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3180                              <1> 	;
  3181                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3182                              <1> K50:					; ALMOST-NUM-STATE
  3183 0000128D F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3184 00001290 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3185 00001292 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3186                              <1> 	;
  3187                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3188                              <1> K52:					; NOT A NUMPAD KEY
  3189 00001294 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3190                              <1> 	;jne	short K53		; JUMP IF NOT
  3191                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3192 00001296 74AF                <1> 	je	short K45B		
  3193                              <1> 	;
  3194                              <1> 	;-----	MUST BE F11 OR F12 
  3195                              <1> K53:					; F1 - F10 COME HERE, TOO
  3196 00001298 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3197 0000129B 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3198                              <1> 		; 20/02/2015 
  3199 0000129D BB[68650000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3200 000012A2 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3201                              <1> 	;
  3202                              <1> 	;-----	TRANSLATE THE CHARACTER
  3203                              <1> K56:					; TRANSLATE-CHAR
  3204 000012A4 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3205 000012A6 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3206 000012A7 F605[C6650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3207 000012AE 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3208 000012B0 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3209 000012B2 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3210                              <1> 	;
  3211                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3212                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3213 000012B4 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3214 000012B6 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3215 000012B7 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3216 000012B9 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3217 000012BB F605[C6650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3218 000012C2 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3219 000012C4 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3220                              <1> 	;
  3221                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3222                              <1> K57:					; BUFFER_FILL
  3223 000012C6 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3224 000012C8 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3225                              <1> 	; 24/12/2021
  3226                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3227 000012CA 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3228                              <1> 	; 24/12/2021
  3229 000012CD 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3230                              <1> 	;je	K26			; INTERRUPT_RETURN
  3231                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3232 000012CF E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3233                              <1> K61:					; NOT-CAPS-STATE
  3234 000012D4 8B1D[D4650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3235 000012DA 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3236 000012DC E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3237 000012E1 3B1D[D0650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3238 000012E7 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3239 000012E9 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3240 000012EC 891D[D4650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3241 000012F2 E945FDFFFF          <1> 	jmp	K26
  3242                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3243                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3244                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3245                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3246                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3247                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3248                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3249                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3250                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3251                              <1> 	;;jmp   K27                    
  3252                              <1> 	;
  3253                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3254                              <1> K62:
  3255 000012F7 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3256 000012F9 E620                <1> 	out	INTA00, al
  3257 000012FB 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3258 000012FF B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3259 00001301 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3260 00001306 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3261                              <1> 
  3262                              <1> SHIP_IT:
  3263                              <1> 	;---------------------------------------------------------------------------------
  3264                              <1> 	; SHIP_IT
  3265                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3266                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3267                              <1> 	;---------------------------------------------------------------------------------
  3268                              <1> 	;
  3269                              <1> 	;push	ax			; SAVE DATA TO SEND
  3270                              <1> 	; 24/12/2021
  3271 0000130B 50                  <1> 	push	eax
  3272                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3273 0000130C FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3274                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3275 0000130D B900000100          <1> 	mov	ecx, 10000h			
  3276                              <1> S10:
  3277 00001312 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3278 00001314 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3279 00001316 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3280                              <1> 
  3281                              <1> 	;pop	ax			; GET DATA TO SEND
  3282                              <1> 	; 24/12/2021
  3283 00001318 58                  <1> 	pop	eax
  3284 00001319 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3285 0000131B FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3286 0000131C C3                  <1> 	retn				; RETURN TO CALLER
  3287                              <1> 
  3288                              <1> SND_DATA:
  3289                              <1> 	; ---------------------------------------------------------------------------------
  3290                              <1> 	; SND_DATA
  3291                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3292                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3293                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3294                              <1> 	; ---------------------------------------------------------------------------------
  3295                              <1> 	;
  3296                              <1> 	;push	ax			; SAVE REGISTERS
  3297                              <1> 	;push	bx
  3298                              <1> 	; 24/12/2021
  3299 0000131D 50                  <1> 	push	eax
  3300 0000131E 53                  <1> 	push	ebx
  3301 0000131F 51                  <1> 	push	ecx
  3302 00001320 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3303 00001322 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3304                              <1> SD0:
  3305 00001324 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3306 00001325 8025[C5650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3307                              <1> 	;
  3308                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3309 0000132C B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3310                              <1> SD5:
  3311 00001331 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3312 00001333 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3313 00001335 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3314                              <1> 	;
  3315 00001337 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3316 00001339 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3317 0000133B FB                  <1> 	sti				; ENABLE INTERRUPTS
  3318                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3319 0000133C B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3320                              <1> SD1:
  3321 00001341 F605[C5650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3322 00001348 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3323 0000134A E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3324                              <1> SD2:
  3325 0000134C FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3326 0000134E 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3327 00001350 800D[C5650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3328 00001357 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3329                              <1> SD3:
  3330 00001359 F605[C5650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3331 00001360 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3332                              <1> SD4:	
  3333 00001362 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3334                              <1> 	;pop	bx
  3335                              <1> 	;pop	ax
  3336                              <1> 	; 24/12/2021
  3337 00001363 5B                  <1> 	pop	ebx
  3338 00001364 58                  <1> 	pop	eax
  3339 00001365 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3340                              <1> 
  3341                              <1> SND_LED:
  3342                              <1> 	; ---------------------------------------------------------------------------------
  3343                              <1> 	; SND_LED
  3344                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3345                              <1> 	;
  3346                              <1> 	;----------------------------------------------------------------------------------
  3347                              <1> 	;
  3348 00001366 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3349 00001367 F605[C5650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3350 0000136E 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3351                              <1> 	;
  3352 00001370 800D[C5650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3353 00001377 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3354 00001379 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3355 0000137B EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3356                              <1> SND_LED1:
  3357 0000137D FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3358 0000137E F605[C5650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3359 00001385 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3360                              <1> 	;
  3361 00001387 800D[C5650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3362                              <1> SL0:
  3363 0000138E B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3364 00001390 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3365 00001395 FA                  <1> 	cli
  3366 00001396 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3367 0000139B 8025[C5650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3368 000013A2 0805[C5650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3369 000013A8 F605[C5650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3370 000013AF 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3371                              <1> 	;
  3372 000013B1 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3373 000013B6 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3374 000013B7 F605[C5650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3375 000013BE 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3376                              <1> SL2:
  3377 000013C0 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3378 000013C2 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3379 000013C7 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3380                              <1> SL3:
  3381 000013C8 8025[C5650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3382                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3383 000013CF FB                  <1> 	sti				; ENABLE INTERRUPTS
  3384 000013D0 C3                  <1> 	retn				; RETURN TO CALLER
  3385                              <1> 
  3386                              <1> MAKE_LED:
  3387                              <1> 	;---------------------------------------------------------------------------------
  3388                              <1> 	; MAKE_LED
  3389                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3390                              <1> 	;	THE MODE INDICATORS.
  3391                              <1> 	;---------------------------------------------------------------------------------
  3392                              <1> 	;
  3393                              <1> 	;push 	cx			; SAVE CX
  3394 000013D1 A0[C3650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3395 000013D6 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3396                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3397                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3398 000013D8 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3399 000013DB 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3400                              <1> 	;pop	cx
  3401 000013DD C3                  <1> 	retn				; RETURN TO CALLER
  3402                              <1> 
  3403                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3404                              <1> 
  3405                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1829                                  
  1830                                  %include 'video.inc' ; 07/03/2015
  1831                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1832                              <1> ; Last Modification: 25/02/2022
  1833                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1834                              <1> ;
  1835                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1836                              <1> 
  1837                              <1> ; 02/02/2022 (simplified scroll up)
  1838                              <1> ; 16/01/2016
  1839                              <1> ; 30/06/2015
  1840                              <1> ; 27/06/2015
  1841                              <1> ; 11/03/2015
  1842                              <1> ; 02/09/2014
  1843                              <1> ; 30/08/2014
  1844                              <1> ; VIDEO FUNCTIONS
  1845                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1846                              <1> 
  1847                              <1> write_tty:
  1848                              <1> 	; 02/02/2022
  1849                              <1> 	; 13/08/2015
  1850                              <1> 	; 02/09/2014
  1851                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1852                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1853                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1854                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1855                              <1> 	;
  1856                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1857                              <1> 	;	   AL = Character to be written
  1858                              <1> 	;	   EBX = Video Page (0 to 7)
  1859                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1860                              <1> 
  1861                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1862                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1863                              <1> 
  1864                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1865                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1866                              <1> ;
  1867                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1868                              <1> ;
  1869                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1870                              <1> ;										:
  1871                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1872                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1873                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1874                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1875                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1876                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1877                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1878                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1879                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1880                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1881                              <1> ;   THE 0 COLOR IS USED.							:
  1882                              <1> ;   ENTRY --									:
  1883                              <1> ;     (AH) = CURRENT CRT MODE							:
  1884                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1885                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1886                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1887                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1888                              <1> ;   EXIT -- 									:
  1889                              <1> ;     ALL REGISTERS SAVED							:
  1890                              <1> ;--------------------------------------------------------------------------------
  1891                              <1> 
  1892 000013DE FA                  <1> 	cli
  1893                              <1> 	;
  1894                              <1> 	; READ CURSOR (04/12/2013)
  1895                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1896 000013DF 08FF                <1> 	or	bh, bh
  1897                              <1> 	;jnz	beeper
  1898                              <1> 	; 02/02/2022
  1899 000013E1 7405                <1> 	jz	short u14
  1900 000013E3 E992000000          <1> 	jmp	beeper
  1901                              <1> u14:
  1902                              <1> 	; 02/02/2022
  1903                              <1> 	;; 01/09/2014
  1904                              <1> 	;cmp	byte [CRT_MODE], 3
  1905                              <1> 	;je	short m3
  1906                              <1> 	;;
  1907                              <1> 	;call	set_mode
  1908                              <1> m3:
  1909 000013E8 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1910                              <1> 	;shl	si, 1
  1911                              <1> 	; 02/02/2022
  1912 000013EA D1E6                <1> 	shl	esi, 1
  1913 000013EC 81C6[B66B0000]      <1> 	add	esi, cursor_posn
  1914 000013F2 668B16              <1> 	mov	dx, [esi]
  1915                              <1> 	;
  1916                              <1> 	; dx now has the current cursor position
  1917                              <1> 	;
  1918 000013F5 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1919 000013F7 7647                <1> 	jbe	short u8
  1920                              <1> 	;
  1921                              <1> 	; write the char to the screen
  1922                              <1> u0:	
  1923                              <1> 	; ah = attribute/color
  1924                              <1> 	; al = character
  1925                              <1> 	; bl = video page number (0 to 7)
  1926                              <1> 	; bh = 0
  1927                              <1> 	;
  1928 000013F9 E8D6010000          <1> 	call	write_c_current
  1929                              <1> 	;
  1930                              <1> 	; position the cursor for next char
  1931 000013FE FEC2                <1> 	inc	dl		; next column
  1932                              <1> 	;cmp	dl, [CRT_COLS]
  1933 00001400 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1934                              <1>         ;jne	set_cpos
  1935                              <1> 	; 02/02/2022
  1936 00001403 7405                <1> 	je	short u13
  1937 00001405 E9DE000000          <1> 	jmp	set_cpos
  1938                              <1> u13:
  1939 0000140A B200                <1> 	mov	dl, 0		; column = 0
  1940                              <1> u10:				; (line feed found)
  1941 0000140C 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1942 0000140F 7228                <1> 	jb 	short u6
  1943                              <1> 	;
  1944                              <1> 	; scroll required
  1945                              <1> u1:	
  1946                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1947 00001411 E8D2000000          <1> 	call	set_cpos
  1948                              <1> 	;
  1949                              <1> 	; determine value to fill with during scroll
  1950                              <1> u2:
  1951                              <1> 	; READ_AC_CURRENT		:
  1952                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1953                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1954                              <1> 	;
  1955                              <1> 	; INPUT				
  1956                              <1> 	;	(AH) = CURRENT CRT MODE
  1957                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1958                              <1> 	;	(DS) = DATA SEGMENT
  1959                              <1> 	;	(ES) = REGEN SEGMENT
  1960                              <1> 	; OUTPUT			
  1961                              <1> 	;	(AL) = CHARACTER READ
  1962                              <1> 	;	(AH) = ATTRIBUTE READ
  1963                              <1> 	;
  1964                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1965                              <1> 	;
  1966                              <1> 	; bl = video page number
  1967                              <1> 	;
  1968 00001416 E82D010000          <1> 	call	find_position	; get regen location and port address
  1969                              <1> 	; dx = status port
  1970                              <1> 	; esi = cursor location/address
  1971                              <1> p11:
  1972 0000141B FB                  <1> 	sti			; enable interrupts
  1973 0000141C 90                  <1> 	nop			; allow for small interupts window
  1974 0000141D FA                  <1> 	cli			; blocks interrupts for single loop
  1975 0000141E EC                  <1> 	in	al, dx		; get status from adapter
  1976 0000141F A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1977 00001421 75F8                <1> 	jnz	short p11	; wait until it is
  1978                              <1> p12:				; now wait for either retrace high
  1979 00001423 EC                  <1> 	in	al, dx		; get status
  1980 00001424 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1981 00001426 74FB                <1> 	jz	short p12	; wait until either is active	
  1982                              <1> p13:
  1983 00001428 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1984 0000142E 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1985                              <1> 	;
  1986                              <1> 	; al = character, ah = attribute
  1987                              <1> 	;
  1988 00001431 FB                  <1> 	sti
  1989                              <1> 	; bl = video page number 	
  1990                              <1> u3:
  1991                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1992                              <1> 	;;sub	cx, cx		; upper left corner
  1993                              <1> 	;;mov	dh, 25-1 	; lower right row
  1994                              <1> 	;;;mov	dl, [CRT_COLS]
  1995                              <1> 	;mov	dl, 80		; lower right column	
  1996                              <1> 	;;dec	dl
  1997                              <1> 	;;mov	dl, 79
  1998                              <1> 
  1999                              <1> 	;;call	scroll_up	; 04/12/2013
  2000                              <1> 	;;; 11/03/2015
  2001                              <1> 	; 02/09/2014
  2002                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2003                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2004                              <1> 	; 11/03/2015
  2005                              <1> 	;sub	cx, cx
  2006                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2007                              <1> 	;
  2008                              <1> 	; 02/02/2022 (simplied scroll up)
  2009                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2010                              <1> 	;
  2011 00001432 B001                <1> 	mov	al, 1		; scroll 1 line up
  2012                              <1> 		; ah = attribute
  2013 00001434 E939010000          <1> 	jmp	scroll_up
  2014                              <1> ;u4:
  2015                              <1> 	;;int	10h		; video-call return
  2016                              <1> 				; scroll up the screen
  2017                              <1> 				; tty return
  2018                              <1> ;u5:
  2019                              <1> 	;retn			; return to the caller
  2020                              <1> 
  2021                              <1> u6:				; set-cursor-inc
  2022 00001439 FEC6                <1> 	inc	dh		; next row
  2023                              <1> 				; set cursor
  2024                              <1> ;u7:					
  2025                              <1> 	;;mov	ah, 02h
  2026                              <1> 	;;jmp	short u4 	; establish the new cursor
  2027                              <1> 	;call	set_cpos
  2028                              <1> 	;jmp 	short u5
  2029 0000143B E9A8000000          <1> 	jmp     set_cpos
  2030                              <1> 
  2031                              <1> 	; check for control characters
  2032                              <1> u8:
  2033 00001440 7434                <1> 	je	short u9
  2034 00001442 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2035 00001444 74C6                <1> 	je	short u10
  2036 00001446 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2037 00001448 7430                <1> 	je	short u11
  2038 0000144A 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2039                              <1> 	;jne	short u0
  2040 0000144C 7420                <1> 	je	short bs	; 12/12/2013
  2041                              <1> 	; 12/12/2013 (tab stop)
  2042 0000144E 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2043 00001450 75A7                <1> 	jne	short u0
  2044 00001452 88D0                <1> 	mov	al, dl
  2045 00001454 6698                <1> 	cbw
  2046 00001456 B108                <1> 	mov	cl, 8
  2047 00001458 F6F1                <1> 	div	cl
  2048 0000145A 28E1                <1> 	sub	cl, ah
  2049                              <1> ts:
  2050                              <1> 	; 02/09/2014
  2051                              <1> 	; 01/09/2014
  2052 0000145C B020                <1> 	mov	al, 20h
  2053                              <1> tsloop:
  2054                              <1> 	;push	cx
  2055                              <1> 	;push	ax
  2056                              <1> 	; 02/02/2022
  2057 0000145E 51                  <1> 	push	ecx
  2058 0000145F 50                  <1> 	push	eax
  2059 00001460 30FF                <1> 	xor 	bh, bh
  2060                              <1> 	;mov	bl, [active_page]
  2061 00001462 E881FFFFFF          <1> 	call	m3
  2062                              <1> 	; 02/02/2022
  2063 00001467 58                  <1> 	pop	eax
  2064 00001468 59                  <1>  	pop	ecx
  2065                              <1> 	;pop	ax  ; ah = attribute/color
  2066                              <1> 	;pop	cx
  2067 00001469 FEC9                <1> 	dec	cl
  2068 0000146B 75F1                <1> 	jnz	short tsloop
  2069 0000146D C3                  <1> 	retn
  2070                              <1> bs:	
  2071                              <1> 	; back space found
  2072 0000146E 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2073                              <1> 	;je	short u7 	; set_cursor
  2074 00001470 7476                <1> 	jz	short set_cpos
  2075                              <1> 	;dec	dx     		; no -- just move it back
  2076                              <1> 	; 02/02/2022
  2077 00001472 FECA                <1> 	dec	dl
  2078                              <1> 	;jmp	short u7
  2079 00001474 EB72                <1> 	jmp	short set_cpos
  2080                              <1> 
  2081                              <1> 	; carriage return found
  2082                              <1> u9:
  2083 00001476 B200                <1> 	mov	dl, 0 		; move to first column
  2084                              <1> 	;jmp	short u7
  2085 00001478 EB6E                <1> 	jmp	short set_cpos
  2086                              <1> 
  2087                              <1> 	; line feed found
  2088                              <1> ;u10:
  2089                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2090                              <1> ;	jne	short u6 	; no, just set the cursor
  2091                              <1> ;       jmp     u1              ; yes, scroll the screen
  2092                              <1> 
  2093                              <1> beeper: 
  2094                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2095                              <1> 	; 18/01/2014
  2096                              <1> 	; 03/12/2013
  2097                              <1> 	; bell found
  2098                              <1> u11:
  2099 0000147A FB                  <1> 	sti
  2100 0000147B 3A1D[C66B0000]      <1> 	cmp	bl, [active_page]
  2101 00001481 7551                <1> 	jne	short u12	; Do not sound the beep 
  2102                              <1> 				; if it is not written on the active page
  2103 00001483 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2104 00001487 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2105                              <1> 	;call	beep		; sound the pod bell
  2106                              <1> 	;jmp	short u5 	; tty_return
  2107                              <1> 	;retn
  2108                              <1> 	
  2109                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2110                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2111                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2112                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2113                              <1> 
  2114                              <1> beep:
  2115                              <1> 	; 07/02/2015
  2116                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2117                              <1> 	; 18/01/2014
  2118                              <1> 	; 03/12/2013
  2119                              <1> 	;
  2120                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2121                              <1> 	;
  2122                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2123                              <1> 	;
  2124                              <1> 	; ENTRY:
  2125                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2126                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2127                              <1> 	; EXIT:			:
  2128                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2129                              <1> 
  2130 00001489 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2131 0000148A FA                  <1> 	cli			; block interrupts during update
  2132 0000148B B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2133 0000148D E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2134 0000148F EB00                <1> 	jmp	$+2		; I/O delay
  2135 00001491 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2136 00001493 E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2137 00001495 EB00                <1> 	jmp	$+2		; I/O delay
  2138 00001497 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2139 00001499 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2140 0000149B E461                <1> 	in	al, PORT_B	; get current setting of port
  2141 0000149D 88C4                <1> 	mov	ah, al		; save that setting
  2142 0000149F 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2143 000014A1 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2144                              <1> 	;popf	; 18/01/2014
  2145 000014A3 FB                  <1> 	sti
  2146                              <1> g7:				; 1/64 second per count (bl)
  2147 000014A4 B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2148 000014A9 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2149 000014AE FECB                <1> 	dec	bl		; (bl) length count expired?
  2150 000014B0 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2151                              <1> 	;
  2152                              <1> 	;pushf			; save interrupt status
  2153 000014B2 FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2154 000014B3 E461                <1> 	in	al, PORT_B	; get current port value
  2155                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2156 000014B5 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2157 000014B7 20C4                <1>         and	ah, al		; someone turned them off during beep
  2158 000014B9 88E0                <1> 	mov	al, ah		; recover value of port
  2159                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2160 000014BB 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2161 000014BD E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2162                              <1> 	;popf			; restore interrupt flag state
  2163 000014BF FB                  <1> 	sti
  2164 000014C0 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2165 000014C5 E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2166                              <1> 	;pushf			; save interrupt status
  2167 000014CA FA                  <1> 	cli			; block interrupts during update
  2168 000014CB E461                <1> 	in	al, PORT_B	; get current port value in case	
  2169 000014CD 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2170 000014CF 08E0                <1> 	or	al, ah		; recover value of port_b
  2171 000014D1 E661                <1> 	out	PORT_B, al	; restore speaker status
  2172 000014D3 9D                  <1> 	popf			; restore interrupt flag state
  2173                              <1> u12:	
  2174 000014D4 C3                  <1> 	retn
  2175                              <1> 
  2176                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2177                              <1> 
  2178                              <1> WAITF:
  2179                              <1> waitf:
  2180                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2181                              <1> 	; 03/12/2013
  2182                              <1> 	;
  2183                              <1> ;	push	ax		; save work register (ah)	
  2184                              <1> ;waitf1:
  2185                              <1> 				; use timer 1 output bits
  2186                              <1> ;	in	al, PORT_B	; read current counter output status
  2187                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2188                              <1> ;	cmp	al, ah		; did it just change
  2189                              <1> ;	je	short waitf1	; wait for a change in output line
  2190                              <1> ;	;
  2191                              <1> ;	mov	ah, al		; save new lflag state
  2192                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2193                              <1> ;	;
  2194                              <1> ;	pop	ax		; restore (ah)
  2195                              <1> ;	retn			; return (cx)=0
  2196                              <1> 
  2197                              <1> ; 02/02/2022
  2198                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2199                              <1> ; 17/12/2014 (dsectrm2.s)
  2200                              <1> ; WAITF
  2201                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2202                              <1> ;
  2203                              <1> ;---WAITF-----------------------------------------------------------------------
  2204                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2205                              <1> ; ENTRY:
  2206                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2207                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2208                              <1> ; EXIT:
  2209                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2210                              <1> ;	(CX) = 0	
  2211                              <1> ;-------------------------------------------------------------------------------
  2212                              <1> 
  2213                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2214                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2215                              <1> 
  2216                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2217 000014D5 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2218                              <1> 	;push	ax
  2219                              <1> 	; 16/12/2014
  2220                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2221 000014D6 D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2222                              <1> ;17/12/2014	
  2223                              <1> ;WAITF1:
  2224                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2225                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2226                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2227                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2228                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2229                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2230                              <1> 	;
  2231                              <1> 	; 17/12/2014
  2232                              <1> 	;
  2233                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2234                              <1> 	;
  2235                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2236                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2237                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2238                              <1> WR_STATE_0:
  2239 000014D8 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2240 000014DA A810                <1> 	TEST	AL,010H
  2241 000014DC 74FA                <1> 	JZ	SHORT WR_STATE_0
  2242                              <1> WR_STATE_1:
  2243 000014DE E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2244 000014E0 A810                <1> 	TEST	AL,010H
  2245 000014E2 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2246 000014E4 E2F2                <1>         LOOP    WR_STATE_0
  2247                              <1> 	;
  2248                              <1> 	;pop	ax
  2249 000014E6 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2250 000014E7 C3                  <1> 	RETn				; (CX) = 0
  2251                              <1> 
  2252                              <1> set_cpos:
  2253                              <1> 	; 25/02/2022
  2254                              <1> 	; 23/02/2022
  2255                              <1> 	; 02/02/2022
  2256                              <1> 	; 27/06/2015
  2257                              <1> 	; 01/09/2014
  2258                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2259                              <1> 	;
  2260                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2261                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2262                              <1> 	;
  2263                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2264                              <1> 	;
  2265                              <1> 	; SET_CPOS
  2266                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2267                              <1> 	;	NEW X-Y VALUES PASSED
  2268                              <1> 	; INPUT
  2269                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2270                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2271                              <1> 	; OUTPUT
  2272                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2273                              <1> 	;
  2274 000014E8 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2275 000014EB D0E0                <1>         shl     al, 1   ; word offset
  2276 000014ED BE[B66B0000]        <1> 	mov	esi, cursor_posn
  2277 000014F2 01C6                <1>         add     esi, eax
  2278 000014F4 668916              <1> 	mov	[esi], dx ; save the pointer
  2279 000014F7 381D[C66B0000]      <1> 	cmp	[active_page], bl
  2280 000014FD 7536                <1> 	jne	short m17
  2281                              <1> 	
  2282 000014FF FA                  <1> 	cli ; 25/02/2022
  2283                              <1> 
  2284                              <1> 	;call	m18	; CURSOR SET
  2285                              <1> ;m17:			; SET_CPOS_RETURN
  2286                              <1> 	; 01/09/2014
  2287                              <1> 	;retn
  2288                              <1> 		; DX = row/column
  2289                              <1> m18:
  2290 00001500 E835000000          <1> 	call	position ; determine location in regen buffer	
  2291                              <1> 	;mov	cx, [CRT_START]
  2292                              <1> 	; 23/02/2022
  2293 00001505 0FB70D[B46B0000]    <1> 	movzx	ecx, word [CRT_START]
  2294 0000150C 01C1                <1> 	add	ecx, eax
  2295                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2296                              <1> 			; to the start address (offset) for this page
  2297                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2298                              <1> 	; 23/02/2022
  2299 0000150E D1E9                <1> 	shr	ecx, 1
  2300 00001510 B40E                <1> 	mov	ah, 14	; register number for cursor
  2301                              <1> 	
  2302 00001512 E802000000          <1> 	call	m16	; output value to the 6845
  2303 00001517 FB                  <1> 	sti	; 25/02/2022
  2304 00001518 C3                  <1> 	retn
  2305                              <1> 
  2306                              <1> 	; 25/02/2022
  2307                              <1> 	; 02/02/2022
  2308                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2309                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2310                              <1> m16:
  2311                              <1> 	;cli	; 25/02/2022
  2312                              <1> 	;mov	dx, [addr_6845] ; address register
  2313 00001519 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2314 0000151D 88E0                <1> 	mov	al, ah	; get value
  2315 0000151F EE                  <1> 	out	dx, al	; register set
  2316                              <1> 	;inc	dx	; data register
  2317                              <1> 	; 02/02/2022
  2318 00001520 FEC2                <1> 	inc	dl
  2319 00001522 EB00                <1> 	jmp	$+2	; i/o delay
  2320 00001524 88E8                <1> 	mov	al, ch	; data
  2321 00001526 EE                  <1> 	out	dx, al	
  2322                              <1> 	;dec	dx
  2323                              <1> 	; 02/02/2022	
  2324 00001527 FECA                <1> 	dec	dl
  2325 00001529 88E0                <1> 	mov	al, ah
  2326 0000152B FEC0                <1> 	inc	al	; point to other data register
  2327 0000152D EE                  <1> 	out	dx, al	; set for second register
  2328                              <1> 	;inc	dx
  2329                              <1> 	; 02/02/2022
  2330 0000152E FEC2                <1> 	inc	dl
  2331 00001530 EB00                <1> 	jmp	$+2	; i/o delay
  2332 00001532 88C8                <1> 	mov	al, cl	; second data value
  2333 00001534 EE                  <1> 	out	dx, al
  2334                              <1> 	;sti	; 25/02/2022
  2335                              <1> m17:
  2336 00001535 C3                  <1> 	retn
  2337                              <1> 
  2338                              <1> set_ctype:
  2339                              <1> 	; 07/02/2022
  2340                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2341                              <1> 	;
  2342                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2343                              <1> 
  2344                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2345                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2346                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2347                              <1> ;          OR NO CURSOR AT ALL
  2348                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2349                              <1> 
  2350                              <1> ;------------------------------------------------
  2351                              <1> ; SET_CTYPE
  2352                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2353                              <1> ; INPUT
  2354                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2355                              <1> ; OUTPUT	
  2356                              <1> ;	NONE
  2357                              <1> ;------------------------------------------------
  2358                              <1> 
  2359 00001536 B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2360                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2361                              <1> 	;call	m16	; output cx register
  2362                              <1> 	;retn
  2363                              <1> 	; 07/02/2022
  2364 00001538 EBDF                <1> 	jmp	m16
  2365                              <1> 
  2366                              <1> position:
  2367                              <1> 	; 23/02/2022
  2368                              <1> 	; 02/02/2022
  2369                              <1> 	; 27/06/2015
  2370                              <1> 	; 02/09/2014
  2371                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2372                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2373                              <1> 	;
  2374                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2375                              <1> 	;
  2376                              <1> 	; POSITION
  2377                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2378                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2379                              <1> 	; INPUT
  2380                              <1> 	;	AX = ROW, COLUMN POSITION
  2381                              <1> 	; OUTPUT
  2382                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2383                              <1> 
  2384                              <1> 		; DX = ROW, COLUMN POSITION
  2385                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2386 0000153A 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2387 0000153C B050                <1> 	mov	al, 80	; determine bytes to row	
  2388 0000153E F6E6                <1> 	mul	dh	; row value
  2389                              <1> 	;xor	dh, dh	; 0
  2390                              <1> 	;add	ax, dx	; add column value to the result
  2391                              <1> 	; 23/02/2022
  2392 00001540 00D0                <1> 	add	al, dl
  2393 00001542 80D400              <1> 	adc	ah, 0	
  2394                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2395                              <1> 	; 02/02/2022
  2396 00001545 D1E0                <1> 	shl	eax, 1
  2397                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2398 00001547 C3                  <1> 	retn
  2399                              <1> 
  2400                              <1> find_position:
  2401                              <1> 	; 02/02/2022
  2402                              <1> 	; 27/06/2015
  2403                              <1> 	; 07/09/2014
  2404                              <1> 	; 02/09/2014
  2405                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2406                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2407 00001548 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2408 0000154B 89CE                <1> 	mov	esi, ecx
  2409                              <1> 	;shl	si, 1
  2410                              <1> 	; 02/02/2022
  2411 0000154D D1E6                <1> 	shl	esi, 1
  2412 0000154F 668B96[B66B0000]    <1> 	mov	dx, [esi+cursor_posn]
  2413 00001556 7409                <1> 	jz	short p21
  2414                              <1> 	;xor	si, si
  2415                              <1> 	; 02/02/2022
  2416 00001558 31F6                <1> 	xor	esi, esi
  2417                              <1> p20:
  2418                              <1> 	;add	si, [CRT_LEN]
  2419 0000155A 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2420 0000155F E2F9                <1> 	loop	p20
  2421                              <1> p21:
  2422 00001561 6621D2              <1> 	and	dx, dx
  2423 00001564 7407                <1> 	jz	short p22
  2424 00001566 E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2425 0000156B 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2426                              <1> p22:	
  2427                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2428                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2429                              <1> 	;add	dx, 6	; point at status port
  2430 0000156D 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2431                              <1> 	; cx = 0
  2432 00001571 C3                  <1> 	retn
  2433                              <1> 
  2434                              <1> scroll_up:
  2435                              <1> 	; 02/02/2022 (simplified scroll up)
  2436                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2437                              <1> 	; 16/01/2016
  2438                              <1> 	; 07/09/2014
  2439                              <1> 	; 02/09/2014
  2440                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2441                              <1> 	; 04/04/2014
  2442                              <1> 	; 04/12/2013
  2443                              <1> 	;
  2444                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2445                              <1> 	;
  2446                              <1> 	; SCROLL UP
  2447                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2448                              <1> 	;	ON THE SCREEN
  2449                              <1> 	; INPUT
  2450                              <1> 	;	(AH) = CURRENT CRT MODE
  2451                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2452                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2453                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2454                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2455                              <1> 	;	(DS) = DATA SEGMENT
  2456                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2457                              <1> 	; OUTPUT
  2458                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2459                              <1> 	;
  2460                              <1> 	;	bh = 0  (02/09/2014)
  2461                              <1> 	;
  2462                              <1> 	; ((ah = 3))
  2463                              <1> 	; cl = left upper column
  2464                              <1> 	; ch = left upper row
  2465                              <1> 	; dl = right lower column
  2466                              <1> 	; dh = right lower row
  2467                              <1> 	;
  2468                              <1> 	; al = line count 
  2469                              <1> 	; ah = attribute to be used on blanked line
  2470                              <1> 	; bl = video page number (0 to 7)
  2471                              <1> 	; 
  2472                              <1> 
  2473                              <1> 	; 02/02/2022 'scroll_up' code
  2474                              <1> 	; ------------------------------------------------------
  2475                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2476                              <1> 
  2477                              <1> 	; INPUT:
  2478                              <1> 	;		
  2479                              <1> 	; al = line count 
  2480                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2481                              <1> 	; ah = attribute to be used on blanked line
  2482                              <1> 	; bl = video page number (0 to 7)
  2483                              <1> 
  2484                              <1> 	;cli
  2485 00001572 31C9                <1> 	xor	ecx, ecx
  2486 00001574 88C1                <1> 	mov	cl, al ; line count (cl)
  2487 00001576 BE00800B00          <1> 	mov	esi, 0B8000h
  2488 0000157B 3A1D[C66B0000]      <1> 	cmp	bl, [active_page]
  2489 00001581 7411                <1> 	je	short n1
  2490 00001583 20DB                <1> 	and	bl, bl
  2491 00001585 7422                <1> 	jz	short n3
  2492 00001587 88DD                <1> 	mov	ch, bl ; video page number
  2493                              <1> n0:
  2494 00001589 6681C6A00F          <1> 	add	si, 25*80*2
  2495 0000158E FECD                <1> 	dec	ch
  2496 00001590 75F7                <1> 	jnz	short n0
  2497 00001592 EB15                <1> 	jmp	short n3
  2498                              <1> n1:
  2499 00001594 660335[B46B0000]    <1> 	add	si, [CRT_START]
  2500                              <1> 	;
  2501 0000159B 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2502                              <1> n2:			 ; wait_display_enable
  2503 0000159F EC                  <1> 	in	al, dx	 ; get port
  2504 000015A0 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2505 000015A2 74FB                <1> 	jz	short n2 ; wait_display_enable
  2506 000015A4 B025                <1> 	mov	al, 25h
  2507 000015A6 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2508 000015A8 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2509                              <1> n3:
  2510                              <1> 	; cl = line count
  2511                              <1> 	; ah = attribute/color
  2512 000015A9 89F7                <1> 	mov	edi, esi
  2513 000015AB 20C9                <1> 	and	cl, cl
  2514 000015AD 741F                <1> 	jz	short n6
  2515 000015AF 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2516 000015B4 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2517 000015B8 F366A5              <1> 	rep	movsw
  2518 000015BB B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2519                              <1> n4:
  2520                              <1> 	; ah = character attribute/cocor
  2521 000015BD B020                <1> 	mov	al, 20h ; fill with blanks
  2522 000015BF F366AB              <1> 	rep	stosw
  2523                              <1> 
  2524 000015C2 3A1D[C66B0000]      <1> 	cmp	bl, [active_page]
  2525 000015C8 7503                <1> 	jne	short n5
  2526                              <1> 
  2527                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2528 000015CA B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2529                              <1> 	;mov	dx, 03D8h ; always set color card port
  2530 000015CC EE                  <1> 	out	dx, al
  2531                              <1> n5:
  2532 000015CD C3                  <1> 	retn
  2533                              <1> n6:
  2534                              <1> 	; clear video page
  2535 000015CE 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2536 000015D2 EBE9                <1> 	jmp	short n4
  2537                              <1> 
  2538                              <1> 	; 23/02/2022
  2539                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2540                              <1> 	; ------------------------------------------------------
  2541                              <1> 
  2542                              <1> 	; Test	Line Count
  2543                              <1> 	or	al, al
  2544                              <1> 	jz	short al_set
  2545                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2546                              <1> 	sub	bh, ch
  2547                              <1> 	inc	bh	; adjust difference by 1
  2548                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2549                              <1> 	jne	short al_set ; if not the we're all set
  2550                              <1> 	xor	al, al	; otherwise set al to zero
  2551                              <1> al_set:
  2552                              <1> 	xor	bh, bh	; 0
  2553                              <1> 	;push	ax
  2554                              <1> 	push	eax ; 23/02/2022
  2555                              <1> 	;mov 	esi, [crt_base]
  2556                              <1>         mov     esi, 0B8000h  
  2557                              <1>         cmp     bl, [active_page]
  2558                              <1> 	jne	short n0
  2559                              <1> 	;
  2560                              <1>         mov     ax, [CRT_START]
  2561                              <1>         add     si, ax
  2562                              <1>         jmp     short n1
  2563                              <1> n0:
  2564                              <1>         and     bl, bl
  2565                              <1> 	jz	short n1
  2566                              <1> 	mov	al, bl
  2567                              <1> n0x:
  2568                              <1>         ;add    si, [CRT_LEN]
  2569                              <1>         ;add    esi, 80*25*2 
  2570                              <1>         add     si, 80*25*2
  2571                              <1>         dec	al
  2572                              <1> 	jnz	short n0x
  2573                              <1> n1:	
  2574                              <1>         ; Scroll position
  2575                              <1> 	;push	dx ; 23/02/2022
  2576                              <1> 	mov	dx, cx	; now, upper left position in DX
  2577                              <1> 	call	position
  2578                              <1> 	add	esi, eax
  2579                              <1> 	mov	edi, esi
  2580                              <1> 	;pop	dx	; lower right position in DX
  2581                              <1> 	sub	dx, cx
  2582                              <1> 	inc	dh	; dh = #rows 
  2583                              <1> 	inc	dl	; dl = #cols in block
  2584                              <1> 	;pop	ax	; al = line count, ah = attribute
  2585                              <1> 	pop	eax ; 23/02/2022
  2586                              <1> 	xor	ecx, ecx
  2587                              <1> 	mov	cx, ax
  2588                              <1> 	;mov	ah, [CRT_COLS]
  2589                              <1> 	mov	ah, 80
  2590                              <1> 	mul	ah	; determine offset to from address
  2591                              <1> 	add	ax, ax  ; *2 for attribute byte
  2592                              <1> 	;
  2593                              <1> 	;push	ax	; offset 
  2594                              <1> 	;push	dx
  2595                              <1> 	; 23/02/2022
  2596                              <1> 	push	eax
  2597                              <1> 	push	edx
  2598                              <1> 	;
  2599                              <1> 	; 04/04/2014
  2600                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2601                              <1> n8:                      ; wait_display_enable
  2602                              <1>         in      al, dx   ; get port
  2603                              <1> 	test	al, RVRT ; wait for vertical retrace
  2604                              <1> 	jz	short n8 ; wait_display_enable
  2605                              <1> 	mov	al, 25h
  2606                              <1> 	mov	dl, 0D8h ; address control port
  2607                              <1> 	out	dx, al	; turn off video during vertical retrace
  2608                              <1> 	;pop	dx	; #rows, #cols
  2609                              <1>        	;pop	ax	; offset
  2610                              <1> 	; 23/02/2022
  2611                              <1> 	pop	edx
  2612                              <1> 	pop	eax
  2613                              <1> 	xchg	ax, cx	; 
  2614                              <1> 	; ecx = offset, al = line count, ah = attribute
  2615                              <1> ;n9:
  2616                              <1> 	or	al, al
  2617                              <1>         jz      short n3 
  2618                              <1>         add     esi, ecx ; from address for scroll
  2619                              <1> 	mov	bh, dh  ; #rows in block
  2620                              <1> 	sub	bh, al	; #rows to be moved
  2621                              <1> n2:
  2622                              <1> 	; Move rows
  2623                              <1> 	mov	cl, dl	; get # of cols to move
  2624                              <1> 	push	esi
  2625                              <1> 	push	edi	; save start address
  2626                              <1> n10:
  2627                              <1> 	movsw		; move that line on screen
  2628                              <1> 	dec	cl
  2629                              <1>         jnz     short n10
  2630                              <1> 	pop	edi
  2631                              <1> 	pop	esi	; recover addresses
  2632                              <1>         ;mov    cl, [CRT_COLS] 
  2633                              <1> 	;add	cl, cl
  2634                              <1>         ;mov    ecx, 80*2
  2635                              <1>         mov     cx, 80*2
  2636                              <1>         add     esi, ecx  ; next line
  2637                              <1>         add     edi, ecx
  2638                              <1> 	dec	bh	 ; count of lines to move
  2639                              <1> 	jnz	short n2 ; row loop
  2640                              <1> 	; bh = 0
  2641                              <1> 	mov	dh, al	 ; #rows	
  2642                              <1> n3:
  2643                              <1> 	; attribute in ah
  2644                              <1> 	mov	al, ' '	 ; fill with blanks
  2645                              <1> n3x:
  2646                              <1> 	; Clear rows
  2647                              <1>                 ; dh =  #rows
  2648                              <1>         mov	cl, dl	; get # of cols to clear
  2649                              <1>         push    edi     ; save address
  2650                              <1> n11:
  2651                              <1>         stosw           ; store fill character
  2652                              <1> 	dec	cl
  2653                              <1>         jnz     short n11
  2654                              <1>         pop     edi     ; recover address
  2655                              <1> 	;mov	cl, [CRT_COLS]
  2656                              <1> 	;add	cl, cl
  2657                              <1>         ;mov    ecx, 80*2
  2658                              <1>         mov	cl, 80*2
  2659                              <1>         add     edi, ecx
  2660                              <1> 	dec	dh
  2661                              <1> 	jnz	short n3x ; 16/01/2016
  2662                              <1> 	;
  2663                              <1> 	cmp	bl, [active_page]
  2664                              <1> 	jne	short n6
  2665                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2666                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2667                              <1> 	mov	dx, 03D8h ; always set color card port
  2668                              <1> 	out	dx, al
  2669                              <1> n6:
  2670                              <1> 	retn
  2671                              <1> 
  2672                              <1> %endif
  2673                              <1> 
  2674                              <1> write_c_current:
  2675                              <1> 	; 02/02/2022
  2676                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2677                              <1> 	; 18/01/2014
  2678                              <1> 	; 04/12/2013
  2679                              <1> 	;
  2680                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2681                              <1> 	;
  2682                              <1> 	; WRITE_C_CURRENT
  2683                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2684                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2685                              <1> 	; INPUT	
  2686                              <1> 	;	(AH) = CURRENT CRT MODE
  2687                              <1> 	;	(BH) = DISPLAY PAGE
  2688                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2689                              <1> 	;	(AL) = CHAR TO WRITE
  2690                              <1> 	;	(DS) = DATA SEGMENT
  2691                              <1> 	;	(ES) = REGEN SEGMENT
  2692                              <1> 	; OUTPUT
  2693                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2694                              <1> 
  2695 000015D4 FA                  <1> 	cli		
  2696                              <1> 	; bl = video page
  2697                              <1> 	; al = character
  2698                              <1> 	; ah = color/attribute
  2699                              <1> 	;push	dx
  2700                              <1> 	;push	ax	; save character & attribute/color
  2701                              <1> 	; 02/02/2022
  2702 000015D5 52                  <1> 	push	edx
  2703 000015D6 50                  <1> 	push	eax
  2704 000015D7 E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2705                              <1> 	; esi = regen location
  2706                              <1> 	; dx = status port
  2707                              <1> 	;
  2708                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2709                              <1> 	;
  2710                              <1> p41:			; wait for horizontal retrace is low or vertical
  2711 000015DC FB                  <1> 	sti		; enable interrupts first
  2712 000015DD 3A1D[C66B0000]      <1>         cmp     bl, [active_page]
  2713 000015E3 7510                <1> 	jne	short p44 
  2714 000015E5 FA                  <1> 	cli 		; block interrupts for single loop
  2715 000015E6 EC                  <1> 	in	al, dx	; get status from the adapter
  2716 000015E7 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2717 000015E9 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2718 000015EB A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2719 000015ED 75ED                <1> 	jnz	short p41 ; wait until it is
  2720                              <1> p42:			; wait for either retrace high
  2721 000015EF EC                  <1> 	in	al, dx	; get status again
  2722 000015F0 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2723 000015F2 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2724                              <1> p43:	
  2725 000015F4 FB                  <1> 	sti
  2726                              <1> p44:
  2727                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2728                              <1> 	; 02/02/2022
  2729 000015F5 58                  <1> 	pop	eax
  2730 000015F6 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2731                              <1> 			; Retro UNIX 386 v1 feature only!
  2732 000015FC 668906              <1> 	mov	[esi], ax
  2733                              <1> 	;pop	dx
  2734                              <1> 	; 02/02/2022
  2735 000015FF 5A                  <1> 	pop	edx
  2736 00001600 C3                  <1> 	retn
  2737                              <1> 
  2738                              <1> %if 0	; 02/02/2022
  2739                              <1> 
  2740                              <1> set_mode:
  2741                              <1> 	; 02/02/2022
  2742                              <1> 	; 16/01/2016
  2743                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2744                              <1> 	;
  2745                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2746                              <1> 
  2747                              <1> ;------------------------------------------------------
  2748                              <1> ; SET MODE					      :
  2749                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2750                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2751                              <1> ; INPUT						      :
  2752                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2753                              <1> ; OUTPUT					      :
  2754                              <1> ;	NONE					      :
  2755                              <1> ;------------------------------------------------------
  2756                              <1> 
  2757                              <1> 	push	edi ; 16/01/2016
  2758                              <1> 	push	ebx
  2759                              <1> 	push	edx
  2760                              <1> 	push	ecx ; 16/01/2016
  2761                              <1>         push    eax
  2762                              <1> 
  2763                              <1> 	;mov	dx, 03D4h 	; address or color card
  2764                              <1> 	mov	al, 3
  2765                              <1> ;M8:
  2766                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2767                              <1> 	mov	al, 29h
  2768                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2769                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2770                              <1> 	;push	dx  		; save port value
  2771                              <1> 	;add	dx, 4		; point to control register
  2772                              <1> 	mov	dx, 3D8h
  2773                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2774                              <1> 	;pop	dx
  2775                              <1> ;M9:
  2776                              <1> 	mov	ebx, video_params ; initialization table
  2777                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2778                              <1> 	;xchg 	ah, al
  2779                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2780                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2781                              <1> 	
  2782                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2783                              <1> 	; 02/02/2022
  2784                              <1> 	; dx = 3D8h
  2785                              <1> 	xor	ecx, ecx
  2786                              <1> 	mov	cl, 16
  2787                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2788                              <1> M10:			;  initialization loop
  2789                              <1> 	mov	al, ah 	; get 6845 register number
  2790                              <1> 	out	dx, al
  2791                              <1> 	;inc	dx      ; point to data port
  2792                              <1> 	; 02/02/2022
  2793                              <1> 	inc	dl ; 3D9h
  2794                              <1> 	inc	ah	; next register value
  2795                              <1> 	mov	al, [ebx] ; get table value
  2796                              <1> 	out	dx, al	; out to chip
  2797                              <1> 	inc	ebx	; next in table
  2798                              <1> 	;dec	dx	; back to pointer register
  2799                              <1> 	; 02/02/2022
  2800                              <1> 	dec	dl ; 3D8h
  2801                              <1> 	loop	M10	; do the whole table
  2802                              <1> 	
  2803                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2804                              <1> 	;xor	ax, ax  
  2805                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2806                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2807                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2808                              <1> 	; black background, light gray characeter color, space character
  2809                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2810                              <1> ;M13:			  ; clear buffer
  2811                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2812                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2813                              <1> 
  2814                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2815                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2816                              <1> 			 ; prepare to output to video enable port
  2817                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2818                              <1> 	; 02/02/2022
  2819                              <1> 	;mov	dx, 3D8h
  2820                              <1> 	; 
  2821                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2822                              <1> 	mov	al, 29h
  2823                              <1> 	out	dx, al	 ; set video enable port
  2824                              <1> 
  2825                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2826                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2827                              <1> 	;
  2828                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2829                              <1> 	;
  2830                              <1> ;-----	SET CURSOR POSITIONS
  2831                              <1> 	;push	edi
  2832                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2833                              <1> 	mov	edi, cursor_posn
  2834                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2835                              <1> 	xor	eax, eax
  2836                              <1> 	rep 	stosd	; fill with zeroes
  2837                              <1> 	;pop	edi
  2838                              <1> 
  2839                              <1> ;-----	SET UP OVERSCAN REGISTER
  2840                              <1> 	inc	dx	; set overscan port to a default
  2841                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2842                              <1> ;M14:
  2843                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2844                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2845                              <1> 
  2846                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2847                              <1> 	;
  2848                              <1> 	pop	eax
  2849                              <1> 	pop	ecx ; 16/01/2016
  2850                              <1> 	pop	edx
  2851                              <1> 	pop	ebx
  2852                              <1> 	pop	edi ; 16/01/2016
  2853                              <1> 	retn
  2854                              <1> 
  2855                              <1> %endif
  2856                              <1> 	
  2857                              <1> tty_sw:
  2858                              <1> 	; 02/02/2022
  2859                              <1> 	; 30/06/2015
  2860                              <1> 	; 27/06/2015 
  2861                              <1> 	; 07/09/2014
  2862                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2863                              <1> 	;
  2864                              <1> 	; (Modified registers : EAX)
  2865                              <1> 	;
  2866                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2867                              <1> 	;
  2868                              <1> ;act_disp_page:
  2869                              <1> 	; 30/06/2015
  2870                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2871                              <1> 	; 10/12/2013
  2872                              <1> 	; 04/12/2013
  2873                              <1> 	;
  2874                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2875                              <1> 	;
  2876                              <1> 	; ACT_DISP_PAGE
  2877                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2878                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2879                              <1> 	; INPUT
  2880                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2881                              <1> 	; OUTPUT
  2882                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2883                              <1> 
  2884                              <1> 	;cli
  2885                              <1> 
  2886 00001601 53                  <1> 	push	ebx
  2887                              <1> 	;push	cx
  2888                              <1> 	;push	dx
  2889                              <1> 	; 02/02/2022
  2890 00001602 51                  <1> 	push	ecx
  2891 00001603 52                  <1> 	push	edx
  2892                              <1> 	;
  2893 00001604 A2[C66B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2894                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2895                              <1> 	;mov	cx, 25*80*2
  2896                              <1> 	; 02/02/2022
  2897 00001609 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2898                              <1> 	; 27/06/2015
  2899 0000160E 0FB6D8              <1> 	movzx	ebx, al
  2900                              <1> 	; 02/02/2022
  2901 00001611 89D8                <1> 	mov	eax, ebx
  2902                              <1> 	;
  2903                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2904                              <1> 	;mul 	cx	; display page times regen length
  2905                              <1> 	; 02/02/2022
  2906 00001613 F7E1                <1> 	mul	ecx	
  2907                              <1> 	; 10/12/2013
  2908 00001615 66A3[B46B0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2909                              <1> 	;mov	cx, ax	; start address to cx
  2910                              <1> 	; 02/02/2022
  2911 0000161B 89C1                <1> 	mov	ecx, eax
  2912                              <1> 	;sar	cx, 1
  2913                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2914                              <1> 	; 02/02/2022
  2915 0000161D D1E9                <1> 	shr	ecx, 1
  2916 0000161F B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2917 00001621 E8F3FEFFFF          <1> 	call	m16
  2918                              <1> 	;sal	bx, 1
  2919                              <1> 	; 01/09/2014
  2920 00001626 D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2921 00001628 81C3[B66B0000]      <1> 	add	ebx, cursor_posn
  2922 0000162E 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2923 00001631 E8CAFEFFFF          <1> 	call	m18
  2924                              <1> 	;
  2925                              <1> 	;pop	dx
  2926                              <1> 	;pop	cx
  2927                              <1> 	; 02/02/2022
  2928 00001636 5A                  <1> 	pop	edx
  2929 00001637 59                  <1> 	pop	ecx
  2930 00001638 5B                  <1> 	pop	ebx
  2931                              <1> 	;
  2932                              <1> 	;sti
  2933                              <1> 	;
  2934 00001639 C3                  <1> 	retn
  2935                              <1> 
  2936                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2937                              <1> 
  2938                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1831                                  
  1832                                  setup_rtc_int:
  1833                                  ; source: http://wiki.osdev.org/RTC
  1834 0000163A FA                      	cli		; disable interrupts
  1835                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1836                                  	; in order to change this ...
  1837                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1838                                  	; (rate must be above 2 and not over 15)
  1839                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1840 0000163B B08A                    	mov	al, 8Ah 
  1841 0000163D E670                    	out	70h, al ; set index to register A, disable NMI
  1842 0000163F 90                      	nop
  1843 00001640 E471                    	in	al, 71h ; get initial value of register A
  1844 00001642 88C4                    	mov 	ah, al
  1845 00001644 80E4F0                  	and	ah, 0F0h
  1846 00001647 B08A                    	mov	al, 8Ah 
  1847 00001649 E670                    	out	70h, al ; reset index to register A
  1848 0000164B 88E0                    	mov	al, ah
  1849 0000164D 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1850 0000164F E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1851                                  	; enable RTC interrupt
  1852 00001651 B08B                    	mov	al, 8Bh ;
  1853 00001653 E670                    	out	70h, al ; select register B and disable NMI
  1854 00001655 90                      	nop
  1855 00001656 E471                    	in	al, 71h ; read the current value of register B
  1856 00001658 88C4                    	mov	ah, al  ;
  1857 0000165A B08B                    	mov 	al, 8Bh ;
  1858 0000165C E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1859 0000165E 88E0                    	mov	al, ah  ;
  1860 00001660 0C40                    	or	al, 40h ;
  1861 00001662 E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1862 00001664 FB                      	sti
  1863 00001665 C3                      	retn
  1864                                  
  1865                                  ; Write memory information
  1866                                  ; Temporary Code
  1867                                  ; 06/11/2014
  1868                                  ; 14/08/2015 
  1869                                  memory_info:	
  1870 00001666 A1[9C6B0000]            	mov	eax, [memory_size] ; in pages
  1871 0000166B 50                      	push	eax
  1872 0000166C C1E00C                  	shl	eax, 12		   ; in bytes
  1873 0000166F BB0A000000              	mov	ebx, 10
  1874 00001674 89D9                    	mov	ecx, ebx	   ; 10
  1875 00001676 BE[FF670000]            	mov	esi, mem_total_b_str	
  1876 0000167B E8B2000000              	call	bintdstr
  1877 00001680 58                      	pop	eax
  1878 00001681 B107                    	mov	cl, 7
  1879 00001683 BE[23680000]            	mov	esi, mem_total_p_str
  1880 00001688 E8A5000000              	call	bintdstr	
  1881                                  	; 14/08/2015
  1882 0000168D E8BD000000              	call	calc_free_mem
  1883                                  	; edx = calculated free pages
  1884                                  	; ecx = 0
  1885 00001692 A1[A06B0000]            	mov 	eax, [free_pages]
  1886 00001697 39D0                    	cmp	eax, edx ; calculated free mem value 
  1887                                  		; and initial free mem value are same or not?
  1888 00001699 751D                    	jne 	short pmim ; print mem info with '?' if not
  1889 0000169B 52                      	push 	edx ; free memory in pages	
  1890                                  	;mov 	eax, edx
  1891 0000169C C1E00C                  	shl	eax, 12 ; convert page count
  1892                                  			; to byte count
  1893 0000169F B10A                    	mov	cl, 10
  1894 000016A1 BE[43680000]            	mov	esi, free_mem_b_str
  1895 000016A6 E887000000              	call	bintdstr
  1896 000016AB 58                      	pop	eax
  1897 000016AC B107                    	mov	cl, 7
  1898 000016AE BE[67680000]            	mov	esi, free_mem_p_str
  1899 000016B3 E87A000000              	call	bintdstr
  1900                                  pmim:
  1901 000016B8 BE[ED670000]            	mov	esi, msg_memory_info
  1902                                  pmim_nb:	
  1903 000016BD AC                      	lodsb
  1904 000016BE 08C0                    	or	al, al
  1905 000016C0 740D                    	jz	short pmim_ok
  1906 000016C2 56                      	push	esi
  1907 000016C3 31DB                    	xor	ebx, ebx ; 0
  1908                                  			; Video page 0 (bl=0)
  1909 000016C5 B407                    	mov	ah, 07h ; Black background, 
  1910                                  			; light gray forecolor
  1911 000016C7 E812FDFFFF              	call	write_tty
  1912 000016CC 5E                      	pop	esi
  1913 000016CD EBEE                    	jmp	short pmim_nb
  1914                                  pmim_ok:
  1915 000016CF C3                      	retn
  1916                                  
  1917                                  ; Convert binary number to hexadecimal string
  1918                                  ; 10/05/2015  
  1919                                  ; dsectpm.s (28/02/2015)
  1920                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1921                                  ; 01/12/2014
  1922                                  ; 25/11/2014
  1923                                  ;
  1924                                  bytetohex:
  1925                                  	; INPUT ->
  1926                                  	; 	AL = byte (binary number)
  1927                                  	; OUTPUT ->
  1928                                  	;	AX = hexadecimal string
  1929                                  	;
  1930 000016D0 53                      	push	ebx
  1931 000016D1 31DB                    	xor	ebx, ebx
  1932 000016D3 88C3                    	mov	bl, al
  1933 000016D5 C0EB04                  	shr	bl, 4
  1934 000016D8 8A9B[22170000]          	mov	bl, [ebx+hexchrs] 	 	
  1935 000016DE 86D8                    	xchg	bl, al
  1936 000016E0 80E30F                  	and	bl, 0Fh
  1937 000016E3 8AA3[22170000]          	mov	ah, [ebx+hexchrs] 
  1938 000016E9 5B                      	pop	ebx	
  1939 000016EA C3                      	retn
  1940                                  
  1941                                  wordtohex:
  1942                                  	; INPUT ->
  1943                                  	; 	AX = word (binary number)
  1944                                  	; OUTPUT ->
  1945                                  	;	EAX = hexadecimal string
  1946                                  	;
  1947 000016EB 53                      	push	ebx
  1948 000016EC 31DB                    	xor	ebx, ebx
  1949 000016EE 86E0                    	xchg	ah, al
  1950 000016F0 6650                    	push	ax
  1951 000016F2 88E3                    	mov	bl, ah
  1952 000016F4 C0EB04                  	shr	bl, 4
  1953 000016F7 8A83[22170000]          	mov	al, [ebx+hexchrs] 	 	
  1954 000016FD 88E3                    	mov	bl, ah
  1955 000016FF 80E30F                  	and	bl, 0Fh
  1956 00001702 8AA3[22170000]          	mov	ah, [ebx+hexchrs]
  1957 00001708 C1E010                  	shl	eax, 16
  1958 0000170B 6658                    	pop	ax
  1959 0000170D 5B                      	pop	ebx
  1960 0000170E EBC0                    	jmp	short bytetohex
  1961                                  	;mov	bl, al
  1962                                  	;shr	bl, 4
  1963                                  	;mov	bl, [ebx+hexchrs] 	 	
  1964                                  	;xchg	bl, al	 	
  1965                                  	;and	bl, 0Fh
  1966                                  	;mov	ah, [ebx+hexchrs] 
  1967                                  	;pop	ebx	
  1968                                  	;retn
  1969                                  
  1970                                  dwordtohex:
  1971                                  	; INPUT ->
  1972                                  	; 	EAX = dword (binary number)
  1973                                  	; OUTPUT ->
  1974                                  	;	EDX:EAX = hexadecimal string
  1975                                  	;
  1976 00001710 50                      	push	eax
  1977 00001711 C1E810                  	shr	eax, 16
  1978 00001714 E8D2FFFFFF              	call	wordtohex
  1979 00001719 89C2                    	mov	edx, eax
  1980 0000171B 58                      	pop	eax
  1981 0000171C E8CAFFFFFF              	call	wordtohex
  1982 00001721 C3                      	retn
  1983                                  
  1984                                  ; 10/05/2015
  1985                                  hex_digits:
  1986                                  hexchrs:
  1987 00001722 303132333435363738-     	db '0123456789ABCDEF'
  1987 0000172B 39414243444546     
  1988                                  
  1989                                  ; Convert binary number to decimal/numeric string
  1990                                  ; 06/11/2014
  1991                                  ; Temporary Code
  1992                                  ;
  1993                                  
  1994                                  bintdstr:
  1995                                  	; EAX = binary number
  1996                                  	; ESI = decimal/numeric string address
  1997                                  	; EBX = divisor (10)
  1998                                  	; ECX = string length (<=10)
  1999 00001732 01CE                    	add	esi, ecx
  2000                                  btdstr0:
  2001 00001734 4E                      	dec	esi
  2002 00001735 31D2                    	xor	edx, edx
  2003 00001737 F7F3                    	div	ebx
  2004 00001739 80C230                  	add	dl, 30h
  2005 0000173C 8816                    	mov	[esi], dl
  2006 0000173E FEC9                    	dec	cl
  2007 00001740 740C                    	jz	btdstr2
  2008 00001742 09C0                    	or	eax, eax
  2009 00001744 75EE                    	jnz	short btdstr0
  2010                                  btdstr1:
  2011 00001746 4E                      	dec	esi
  2012 00001747 C60620                          mov     byte [esi], 20h ; blank space
  2013 0000174A FEC9                    	dec	cl
  2014 0000174C 75F8                    	jnz	short btdstr1
  2015                                  btdstr2:
  2016 0000174E C3                      	retn
  2017                                  
  2018                                  ; Calculate free memory pages on M.A.T.
  2019                                  ; 06/11/2014
  2020                                  ; Temporary Code
  2021                                  ;
  2022                                  
  2023                                  calc_free_mem:
  2024 0000174F 31D2                    	xor	edx, edx
  2025                                  	;xor	ecx, ecx
  2026 00001751 668B0D[B06B0000]        	mov	cx, [mat_size] ; in pages
  2027 00001758 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2028 0000175B BE00001000              	mov	esi, MEM_ALLOC_TBL
  2029                                  cfm0:
  2030 00001760 AD                      	lodsd
  2031 00001761 51                      	push	ecx
  2032 00001762 B920000000              	mov	ecx, 32
  2033                                  cfm1:
  2034 00001767 D1E8                    	shr	eax, 1
  2035 00001769 7301                    	jnc	short cfm2
  2036 0000176B 42                      	inc	edx
  2037                                  cfm2:
  2038 0000176C E2F9                    	loop	cfm1
  2039 0000176E 59                      	pop	ecx
  2040 0000176F E2EF                    	loop	cfm0
  2041 00001771 C3                      	retn
  2042                                  
  2043                                  %include 'diskio.inc'  ; 07/03/2015
  2044                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2045                              <1> ; Last Modification: 24/12/2021
  2046                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2047                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2048                              <1> 
  2049                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2050                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2051                              <1> 
  2052                              <1> ; 06/02/2015
  2053                              <1> diskette_io:
  2054 00001772 9C                  <1> 	pushfd
  2055 00001773 0E                  <1> 	push 	cs
  2056 00001774 E809000000          <1> 	call 	DISKETTE_IO_1
  2057 00001779 C3                  <1> 	retn
  2058                              <1> 	
  2059                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2060                              <1> ;//////////////////////////////////////////////////////
  2061                              <1> 
  2062                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2063                              <1> 
  2064                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2065                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2066                              <1> ; 20/02/2015
  2067                              <1> ; 06/02/2015 (Retro UNIX 386 v1, unix386.s)
  2068                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2069                              <1> ;
  2070                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2071                              <1> ;
  2072                              <1> ; ADISK.EQU
  2073                              <1> 
  2074                              <1> ;----- Wait control constants 
  2075                              <1> 
  2076                              <1> ;amount of time to wait while RESET is active.
  2077                              <1> 
  2078                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2079                              <1> 					;at 250 KBS xfer rate.
  2080                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2081                              <1> 
  2082                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2083                              <1> 					;status register to become valid
  2084                              <1> 					;before re-reading.
  2085                              <1> 
  2086                              <1> ;After sending a byte to NEC, status register may remain
  2087                              <1> ;incorrectly set for 24 us.
  2088                              <1> 
  2089                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2090                              <1> 					;RQM low.
  2091                              <1> 
  2092                              <1> ; COMMON.MAC
  2093                              <1> ;
  2094                              <1> ;	Timing macros
  2095                              <1> ;
  2096                              <1> 
  2097                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2098                              <1> 		jmp short $+2
  2099                              <1> %endmacro		
  2100                              <1> 
  2101                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2102                              <1> 		jmp short $+2
  2103                              <1> 		jmp short $+2
  2104                              <1> %endmacro
  2105                              <1> 
  2106                              <1> %macro		NEWIODELAY 0
  2107                              <1> 		out	0EBh,al
  2108                              <1> %endmacro 
  2109                              <1> 
  2110                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2111                              <1> ;;; WAIT_FOR_MEM
  2112                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2113                              <1> ;WAIT_FDU_INT_HI	equ	1
  2114                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2115                              <1> ;;; WAIT_FOR_PORT
  2116                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2117                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2118                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2119                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2120                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2121                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2122                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2123                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2124                              <1> ;;; WAIT_REFRESH
  2125                              <1> ;amount of time to wait for head settle, per unit in parameter
  2126                              <1> ;table = 1 ms.
  2127                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2128                              <1> 
  2129                              <1> 
  2130                              <1> ; //////////////// DISKETTE I/O ////////////////
  2131                              <1> 
  2132                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2133                              <1> 
  2134                              <1> ;----------------------------------------
  2135                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2136                              <1> ;----------------------------------------
  2137                              <1> 
  2138                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2139                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2140                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2141                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2142                              <1> 
  2143                              <1> ;----------------------------------------
  2144                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2145                              <1> ;-------------------------------------------------------------------------------
  2146                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2147                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2148                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2149                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2150                              <1> 
  2151                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2152                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2153                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2154                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2155                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2156                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2157                              <1> 
  2158                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2159                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2160                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2161                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2162                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2163                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2164                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2165                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2166                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2167                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2168                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2169                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2170                              <1> 
  2171                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2172                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2173                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2174                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2175                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2176                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2177                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2178                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2179                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2180                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2181                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2182                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2183                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2184                              <1> 
  2185                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2186                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2187                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2188                              <1> 
  2189                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2190                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2191                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2192                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2193                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2194                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2195                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2196                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2197                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2198                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2199                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2200                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2201                              <1> 
  2202                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2203                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2204                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2205                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2206                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2207                              <1> 
  2208                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2209                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2210                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2211                              <1> INTA01		EQU	021H		; 8259 PORT
  2212                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2213                              <1> INTB01		EQU	0A1H		;
  2214                              <1> 
  2215                              <1> ;-------------------------------------------------------------------------------
  2216                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2217                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2218                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2219                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2220                              <1> ;-------------------------------------------------------------------------------
  2221                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2222                              <1> 
  2223                              <1> ;-------------------------------------------------------------------------------
  2224                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2225                              <1> 
  2226                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2227                              <1> ; (unix386.s <-- dsectrm2.s)
  2228                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2229                              <1> 
  2230                              <1> ; 10/12/2014
  2231                              <1> ;
  2232                              <1> ;int40h:
  2233                              <1> ;	pushf
  2234                              <1> ;	push 	cs
  2235                              <1> ;	;cli
  2236                              <1> ;	call 	DISKETTE_IO_1
  2237                              <1> ;	retn
  2238                              <1> 
  2239                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2240                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2241                              <1> ;
  2242                              <1> 
  2243                              <1> ;-- INT13H ---------------------------------------------------------------------
  2244                              <1> ; DISKETTE I/O
  2245                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2246                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2247                              <1> ; INPUT
  2248                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2249                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2250                              <1> ;		ON ALL DRIVES
  2251                              <1> ;------------------------------------------------------------------------------- 
  2252                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2253                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2254                              <1> ;-------------------------------------------------------------------------------
  2255                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2256                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2257                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2258                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2259                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2260                              <1> ;		320/360	320/360	    0-39
  2261                              <1> ;		320/360	1.2M	    0-39
  2262                              <1> ;		1.2M	1.2M	    0-79
  2263                              <1> ;		720K	720K	    0-79
  2264                              <1> ;		1.44M	1.44M	    0-79	
  2265                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2266                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2267                              <1> ;		320/360	320/360	     1-8/9
  2268                              <1> ;		320/360	1.2M	     1-8/9
  2269                              <1> ;		1.2M	1.2M	     1-15
  2270                              <1> ;		720K	720K	     1-9
  2271                              <1> ;		1.44M	1.44M	     1-18		
  2272                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2273                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2274                              <1> ;		320/360	320/360	        8/9
  2275                              <1> ;		320/360	1.2M	        8/9
  2276                              <1> ;		1.2M	1.2M		15
  2277                              <1> ;		720K	720K		9
  2278                              <1> ;		1.44M	1.44M		18
  2279                              <1> ;
  2280                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2281                              <1> ;
  2282                              <1> ;-------------------------------------------------------------------------------
  2283                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2284                              <1> ;-------------------------------------------------------------------------------
  2285                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2286                              <1> ;-------------------------------------------------------------------------------
  2287                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2288                              <1> ;-------------------------------------------------------------------------------
  2289                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2290                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2291                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2292                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2293                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2294                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2295                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2296                              <1> ;		READ/WRITE ACCESS.
  2297                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2298                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2299                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2300                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2301                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2302                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2303                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2304                              <1> ;
  2305                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2306                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2307                              <1> ;		---------------------------------------------
  2308                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2309                              <1> ;		---------------------------------------------
  2310                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2311                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2312                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2313                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2314                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2315                              <1> ;		---------------------------------------------
  2316                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2317                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2318                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2319                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2320                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2321                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2322                              <1> ;-------------------------------------------------------------------------------
  2323                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2324                              <1> ;	REGISTERS
  2325                              <1> ;	  INPUT
  2326                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2327                              <1> ;	  OUTPUT
  2328                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2329                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2330                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2331                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2332                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2333                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2334                              <1> ;	    (BH) - 0
  2335                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2336                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2337                              <1> ;	    (AX) - 0
  2338                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2339                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2340                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2341                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2342                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2343                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2344                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2345                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2346                              <1> ;-------------------------------------------------------------------------------
  2347                              <1> ;	(AH)= 15H  READ DASD TYPE
  2348                              <1> ;	OUTPUT REGISTERS
  2349                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2350                              <1> ;		00 - DRIVE NOT PRESENT	
  2351                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2352                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2353                              <1> ;		03 - RESERVED (FIXED DISK)
  2354                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2355                              <1> ;-------------------------------------------------------------------------------
  2356                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2357                              <1> ;	OUTPUT REGISTERS
  2358                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2359                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2360                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2361                              <1> ;-------------------------------------------------------------------------------
  2362                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2363                              <1> ;	INPUT REGISTERS
  2364                              <1> ;	(AL) -	00 - NOT USED	
  2365                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2366                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2367                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2368                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2369                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2370                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2371                              <1> ;-------------------------------------------------------------------------------
  2372                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2373                              <1> ;	INPUT REGISTERS
  2374                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2375                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2376                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2377                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2378                              <1> ;	OUTPUT REGISTERS:
  2379                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2380                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2381                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2382                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2383                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2384                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2385                              <1> ;-------------------------------------------------------------------------------
  2386                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2387                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2388                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2389                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2390                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2391                              <1> ;		CHANGE ERROR CODE
  2392                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2393                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2394                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2395                              <1> ;
  2396                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2397                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2398                              <1> ;-------------------------------------------------------------------------------
  2399                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2400                              <1> ;	AH = STATUS OF OPERATION
  2401                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2402                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2403                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2404                              <1> ;		TYPE AH=(15)).
  2405                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2406                              <1> ;	FOR READ/WRITE/VERIFY
  2407                              <1> ;		DS,BX,DX,CX PRESERVED
  2408                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2409                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2410                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2411                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2412                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2413                              <1> ;-------------------------------------------------------------------------------
  2414                              <1> ;
  2415                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2416                              <1> ;
  2417                              <1> ;   -----------------------------------------------------------------
  2418                              <1> ;   |       |       |       |       |       |       |       |       |
  2419                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2420                              <1> ;   |       |       |       |       |       |       |       |       |
  2421                              <1> ;   -----------------------------------------------------------------
  2422                              <1> ;	|	|	|	|	|	|	|	|
  2423                              <1> ;	|	|	|	|	|	-----------------
  2424                              <1> ;	|	|	|	|	|		|
  2425                              <1> ;	|	|	|	|    RESERVED		|
  2426                              <1> ;	|	|	|	|		  PRESENT STATE
  2427                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2428                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2429                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2430                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2431                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2432                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2433                              <1> ;	|	|	|	|	110: RESERVED
  2434                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2435                              <1> ;	|	|	|	|
  2436                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2437                              <1> ;	|	|	|
  2438                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2439                              <1> ;	|	|			DRIVE)
  2440                              <1> ;	|	|
  2441                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2442                              <1> ;
  2443                              <1> ;						00: 500 KBS
  2444                              <1> ;						01: 300 KBS
  2445                              <1> ;						10: 250 KBS
  2446                              <1> ;						11: RESERVED
  2447                              <1> ;
  2448                              <1> ;
  2449                              <1> ;-------------------------------------------------------------------------------
  2450                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2451                              <1> ;-------------------------------------------------------------------------------
  2452                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2453                              <1> ;-------------------------------------------------------------------------------
  2454                              <1> 
  2455                              <1> struc MD
  2456 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2457 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2458 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2459 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2460 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2461 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2462 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2463 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2464 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2465 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2466 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2467 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2468 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2469                              <1> endstruc
  2470                              <1> 
  2471                              <1> BIT7OFF	EQU	7FH
  2472                              <1> BIT7ON	EQU	80H
  2473                              <1> 
  2474                              <1> ;;int13h: ; 16/02/2015
  2475                              <1> ;; 16/02/2015 - 21/02/2015
  2476                              <1> int40h:
  2477 0000177A 9C                  <1> 	pushfd
  2478 0000177B 0E                  <1> 	push 	cs
  2479 0000177C E801000000          <1> 	call 	DISKETTE_IO_1
  2480 00001781 C3                  <1> 	retn	
  2481                              <1> 
  2482                              <1> DISKETTE_IO_1:
  2483                              <1> 
  2484 00001782 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2485 00001783 55                  <1> 	PUSH	eBP			; USER REGISTER
  2486 00001784 57                  <1> 	PUSH	eDI			; USER REGISTER
  2487 00001785 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2488 00001786 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2489 00001787 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2490 00001788 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2491                              <1> 					; [BP]   = SECTOR #
  2492                              <1> 					; [BP+1] = TRACK #
  2493                              <1> 					; [BP+2] = BUFFER OFFSET
  2494                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2495                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2496                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2497                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2498                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2499                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2500                              <1> 					; BH/[BP+3] = 0
  2501                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2502                              <1> 					; DH/[BP+5] = MAX HEAD #
  2503                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2504 0000178A 06                  <1> 	push	es ; 06/02/2015	
  2505 0000178B 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2506 0000178C 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2507                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2508                              <1> 	;mov	cx, cs
  2509                              <1> 	;mov	ds, cx
  2510 0000178D 66B91000            <1> 	mov	cx, KDATA
  2511 00001791 8ED9                <1>         mov     ds, cx
  2512 00001793 8EC1                <1>         mov     es, cx
  2513                              <1> 
  2514                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2515 00001795 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2516 00001798 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2517 0000179A B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2518                              <1> OK_FUNC:
  2519 0000179C 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2520 0000179F 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2521 000017A1 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2522 000017A4 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2523 000017A6 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2524 000017A9 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2525 000017AB B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2526                              <1> OK_DRV:
  2527 000017AD 31C9                <1> 	xor	ecx, ecx
  2528                              <1> 	;mov	esi, ecx ; 08/02/2015
  2529                              <1> 	; 24/12/2021
  2530 000017AF 89CE                <1> 	mov	esi, ecx
  2531 000017B1 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2532 000017B3 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2533                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2534                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2535 000017B5 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2536 000017B8 BB[F0170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2537 000017BD 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2538 000017BF 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2539 000017C1 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2540 000017C3 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2541 000017C6 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2542                              <1> 	;
  2543                              <1> 	; 11/12/2014
  2544 000017C9 8815[81660000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2545                              <1> 	;
  2546 000017CF 8A25[1C6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2547 000017D5 C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2548                              <1> 
  2549                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2550                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2551                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2552                              <1> ;
  2553                              <1> ;		DI	: DRIVE #
  2554                              <1> ;		SI-HI	: HEAD #
  2555                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2556                              <1> ;		ES	: BUFFER SEGMENT
  2557                              <1> ;		[BP]	: SECTOR #
  2558                              <1> ;		[BP+1]	: TRACK #
  2559                              <1> ;		[BP+2]	: BUFFER OFFSET
  2560                              <1> ;
  2561                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2562                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2563                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2564                              <1> ;	SPECIFIC ERROR CODE.
  2565                              <1> ;
  2566                              <1> 					; (AH) = @DSKETTE_STATUS
  2567 000017DC FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2568 000017DE 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2569 000017DF 1F                  <1> 	POP	DS
  2570 000017E0 07                  <1> 	pop	es	; 06/02/2015
  2571 000017E1 59                  <1> 	POP	eCX
  2572 000017E2 5B                  <1> 	POP	eBX
  2573 000017E3 5A                  <1> 	POP	eDX
  2574 000017E4 5F                  <1> 	POP	eDI
  2575 000017E5 89E5                <1> 	MOV	eBP, eSP
  2576 000017E7 50                  <1> 	PUSH	eAX
  2577 000017E8 9C                  <1> 	PUSHFd
  2578 000017E9 58                  <1> 	POP	eAX
  2579                              <1> 	;MOV	[BP+6], AX
  2580 000017EA 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2581 000017ED 58                  <1> 	POP	eAX
  2582 000017EE 5D                  <1> 	POP	eBP
  2583 000017EF CF                  <1> 	IRETd
  2584                              <1> 
  2585                              <1> ;-------------------------------------------------------------------------------
  2586                              <1> ; DW --> dd (06/02/2015)
  2587 000017F0 [54180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2588 000017F4 [C9180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2589 000017F8 [D9180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2590 000017FC [EA180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2591 00001800 [FB180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2592 00001804 [0C190000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2593 00001808 [90190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2594 0000180C [90190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2595 00001810 [9C190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2596 00001814 [90190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2597 00001818 [90190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2598 0000181C [90190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2599 00001820 [90190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2600 00001824 [90190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2601 00001828 [90190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2602 0000182C [90190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2603 00001830 [90190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2604 00001834 [90190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2605 00001838 [90190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2606 0000183C [90190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2607 00001840 [90190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2608 00001844 [5B1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2609 00001848 [831A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2610 0000184C [BC1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2611 00001850 [3D1B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2612                              <1> FNC_TAE EQU     $                       ; END
  2613                              <1> 
  2614                              <1> ;-------------------------------------------------------------------------------
  2615                              <1> ; DISK_RESET	(AH = 00H)	
  2616                              <1> ;		RESET THE DISKETTE SYSTEM.
  2617                              <1> ;
  2618                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2619                              <1> ;-------------------------------------------------------------------------------
  2620                              <1> DSK_RESET:
  2621 00001854 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2622 00001858 FA                  <1> 	CLI				; NO INTERRUPTS
  2623 00001859 A0[1A6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2624 0000185E 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2625 00001860 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2626                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2627 00001863 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2628 00001865 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2629 00001866 C605[196C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2630                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2631                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2632                              <1> 					;      PULSE WIDTH)
  2633                              <1> 	; 19/12/2014
  2634                              <1> 	NEWIODELAY
  2107 0000186D E6EB                <2>  out 0EBh,al
  2635                              <1> 
  2636                              <1> 	; 17/12/2014 
  2637                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2638 0000186F B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2639                              <1> wdw1:
  2640                              <1> 	NEWIODELAY   ; 27/02/2015
  2107 00001874 E6EB                <2>  out 0EBh,al
  2641 00001876 E2FC                <1> 	loop	wdw1
  2642                              <1> 	;
  2643 00001878 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2644 0000187A EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2645                              <1> 	; 16/12/2014
  2646                              <1> 	IODELAY
  2102 0000187B EB00                <2>  jmp short $+2
  2103 0000187D EB00                <2>  jmp short $+2
  2647                              <1> 	;
  2648                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2649 0000187F E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2650 00001884 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2651 00001886 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2652                              <1> NXT_DRV:
  2653                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2654                              <1> 	; 24/12/2021
  2655 0000188A 51                  <1> 	push	ecx
  2656 0000188B B8[BF180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2657 00001890 50                  <1> 	PUSH	eAX			; "
  2658 00001891 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2659 00001893 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2660 00001898 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2661 00001899 E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2662                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2663                              <1> 	; 24/12/2021
  2664 0000189E 59                  <1> 	pop	ecx
  2665 0000189F 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2666 000018A1 3A0D[1D6C0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2667 000018A7 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2668 000018A9 FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2669 000018AB 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2670 000018AE 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2671                              <1> 	;
  2672 000018B0 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2673                              <1> RESBAC:
  2674 000018B5 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2675                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2676                              <1> 	; 24/12/2021
  2677 000018BA 89F3                <1> 	mov	ebx, esi
  2678 000018BC 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2679 000018BE C3                  <1> 	RETn		
  2680                              <1> DR_POP_ERR:
  2681                              <1> 	;POP	CX			; CLEAR STACK
  2682                              <1> 	; 24/12/2021
  2683 000018BF 59                  <1> 	pop	ecx
  2684                              <1> DR_ERR:
  2685 000018C0 800D[1C6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2686 000018C7 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2687                              <1> 
  2688                              <1> ;-------------------------------------------------------------------------------
  2689                              <1> ; DISK_STATUS	(AH = 01H)
  2690                              <1> ;	DISKETTE STATUS.
  2691                              <1> ;
  2692                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2693                              <1> ;
  2694                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2695                              <1> ;-------------------------------------------------------------------------------
  2696                              <1> DSK_STATUS:
  2697 000018C9 8825[1C6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2698 000018CF E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2699                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2700                              <1> 	; 24/12/2021
  2701 000018D4 89F3                <1> 	mov	ebx, esi
  2702 000018D6 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2703 000018D8 C3                  <1> 	RETn		
  2704                              <1> 
  2705                              <1> ;-------------------------------------------------------------------------------
  2706                              <1> ; DISK_READ	(AH = 02H)	
  2707                              <1> ;	DISKETTE READ.
  2708                              <1> ;
  2709                              <1> ; ON ENTRY:	DI	: DRIVE #
  2710                              <1> ;		SI-HI	: HEAD #
  2711                              <1> ;		SI-LOW	: # OF SECTORS
  2712                              <1> ;		ES	: BUFFER SEGMENT
  2713                              <1> ;		[BP]	: SECTOR #
  2714                              <1> ;		[BP+1]	: TRACK #
  2715                              <1> ;		[BP+2]	: BUFFER OFFSET
  2716                              <1> ;
  2717                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2718                              <1> ;-------------------------------------------------------------------------------
  2719                              <1> 
  2720                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2721                              <1> 
  2722                              <1> DSK_READ:
  2723 000018D9 8025[1A6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2724 000018E0 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2725 000018E4 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2726 000018E9 C3                  <1> 	RETn
  2727                              <1> 
  2728                              <1> ;-------------------------------------------------------------------------------
  2729                              <1> ; DISK_WRITE	(AH = 03H)
  2730                              <1> ;	DISKETTE WRITE.
  2731                              <1> ;
  2732                              <1> ; ON ENTRY:	DI	: DRIVE #
  2733                              <1> ;		SI-HI	: HEAD #
  2734                              <1> ;		SI-LOW	: # OF SECTORS
  2735                              <1> ;		ES	: BUFFER SEGMENT
  2736                              <1> ;		[BP]	: SECTOR #
  2737                              <1> ;		[BP+1]	: TRACK #
  2738                              <1> ;		[BP+2]	: BUFFER OFFSET
  2739                              <1> ;
  2740                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2741                              <1> ;-------------------------------------------------------------------------------
  2742                              <1> 
  2743                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2744                              <1> 
  2745                              <1> DSK_WRITE:
  2746 000018EA 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2747 000018EE 800D[1A6C0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2748 000018F5 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2749 000018FA C3                  <1> 	RETn
  2750                              <1> 
  2751                              <1> ;-------------------------------------------------------------------------------
  2752                              <1> ; DISK_VERF	(AH = 04H)
  2753                              <1> ;	DISKETTE VERIFY.
  2754                              <1> ;
  2755                              <1> ; ON ENTRY:	DI	: DRIVE #
  2756                              <1> ;		SI-HI	: HEAD #
  2757                              <1> ;		SI-LOW	: # OF SECTORS
  2758                              <1> ;		ES	: BUFFER SEGMENT
  2759                              <1> ;		[BP]	: SECTOR #
  2760                              <1> ;		[BP+1]	: TRACK #
  2761                              <1> ;		[BP+2]	: BUFFER OFFSET
  2762                              <1> ;
  2763                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2764                              <1> ;-------------------------------------------------------------------------------
  2765                              <1> DSK_VERF:
  2766 000018FB 8025[1A6C0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2767 00001902 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2768 00001906 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2769 0000190B C3                  <1> 	RETn
  2770                              <1> 
  2771                              <1> ;-------------------------------------------------------------------------------
  2772                              <1> ; DISK_FORMAT	(AH = 05H)
  2773                              <1> ;	DISKETTE FORMAT.
  2774                              <1> ;
  2775                              <1> ; ON ENTRY:	DI	: DRIVE #
  2776                              <1> ;		SI-HI	: HEAD #
  2777                              <1> ;		SI-LOW	: # OF SECTORS
  2778                              <1> ;		ES	: BUFFER SEGMENT
  2779                              <1> ;		[BP]	: SECTOR #
  2780                              <1> ;		[BP+1]	: TRACK #
  2781                              <1> ;		[BP+2]	: BUFFER OFFSET
  2782                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2783                              <1> ;
  2784                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2785                              <1> ;-------------------------------------------------------------------------------
  2786                              <1> DSK_FORMAT:
  2787 0000190C E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2788 00001911 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2789 00001916 800D[1A6C0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2790 0000191D E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2791 00001922 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2792 00001924 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2793 00001929 E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2794 0000192E 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2795 00001930 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2796                              <1> FM_WR:
  2797 00001935 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2798 0000193A 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2799 0000193C B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2800 0000193E E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2801 00001943 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2802 00001945 B8[81190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2803 0000194A 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2804 0000194B B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2805 0000194D E80E090000          <1> 	CALL	GET_PARM
  2806 00001952 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2807 00001957 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2808 00001959 E802090000          <1> 	CALL	GET_PARM
  2809 0000195E E8030A0000          <1> 	CALL	NEC_OUTPUT
  2810 00001963 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2811 00001965 E8F6080000          <1> 	CALL	GET_PARM
  2812 0000196A E8F7090000          <1> 	CALL	NEC_OUTPUT
  2813 0000196F B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2814 00001971 E8EA080000          <1> 	CALL	GET_PARM
  2815 00001976 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2816 0000197B 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2817 0000197C E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2818                              <1> FM_DON:
  2819 00001981 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2820 00001986 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2821                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2822 0000198B 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2823 0000198D 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2824 0000198F C3                  <1> 	RETn
  2825                              <1> 
  2826                              <1> ;-------------------------------------------------------------------------------
  2827                              <1> ; FNC_ERR
  2828                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2829                              <1> ;	SET BAD COMMAND IN STATUS.
  2830                              <1> ;
  2831                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2832                              <1> ;-------------------------------------------------------------------------------
  2833                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2834                              <1> 	;MOV	AX,SI			; RESTORE AL
  2835                              <1> 	; 24/12/2021
  2836 00001990 89F0                <1> 	mov	eax, esi
  2837 00001992 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2838 00001994 8825[1C6C0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2839 0000199A F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2840 0000199B C3                  <1> 	RETn
  2841                              <1> 
  2842                              <1> ;-------------------------------------------------------------------------------
  2843                              <1> ; DISK_PARMS	(AH = 08H)	
  2844                              <1> ;	READ DRIVE PARAMETERS.
  2845                              <1> ;
  2846                              <1> ; ON ENTRY:	DI : DRIVE #
  2847                              <1> ;
  2848                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2849                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2850                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2851                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2852                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2853                              <1> ;		BH/[BP+3] = 0
  2854                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2855                              <1> ;		DH/[BP+5] = MAX HEAD #
  2856                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2857                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2858                              <1> ;		AX        = 0
  2859                              <1> ;
  2860                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2861                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2862                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2863                              <1> ;		       CALLER.
  2864                              <1> ;-------------------------------------------------------------------------------
  2865                              <1> DSK_PARMS:
  2866 0000199C E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2867                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2868 000019A1 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2869 000019A3 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2870                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2871                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2872                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2873                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2874                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2875                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2876                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2877                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2878                              <1> 	;sub	edx, edx
  2879 000019A6 66A1[8E660000]      <1> 	mov     ax, [fd0_type]
  2880 000019AC 6621C0              <1> 	and     ax, ax
  2881 000019AF 7473                <1> 	jz      short NON_DRV
  2882 000019B1 FEC2                <1> 	inc     dl
  2883 000019B3 20E4                <1> 	and     ah, ah
  2884 000019B5 7402                <1> 	jz      short STO_DL
  2885 000019B7 FEC2                <1> 	inc     dl
  2886                              <1> STO_DL:
  2887                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2888 000019B9 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2889 000019BC 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2890 000019C0 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2891                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2892 000019C2 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2893 000019C6 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2894                              <1> 	;;20/02/2015
  2895                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2896                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2897 000019CB 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2898 000019CD E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2899 000019D2 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2900                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2901 000019D4 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2902 000019D7 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2903 000019DA 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2904 000019DD EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2905                              <1> CHK_EST:
  2906 000019DF 8AA7[296C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2907 000019E5 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2908 000019E8 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2909                              <1> USE_EST:
  2910 000019EA 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2911 000019ED 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2912 000019F0 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2913                              <1> 
  2914                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2915                              <1> 
  2916 000019F2 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2917 000019F4 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2918 000019F9 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2919 000019FC 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2920 000019FF F687[296C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2921 00001A06 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2922                              <1> 
  2923                              <1> ;-----	IT IS 1.44 MB DRIVE
  2924                              <1> 
  2925                              <1> PARM144:
  2926 00001A08 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2927 00001A0A E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2928 00001A0F 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2929 00001A12 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2930                              <1> STO_CX:
  2931 00001A15 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2932                              <1> ES_DI:
  2933                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2934 00001A18 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2935                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2936                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2937                              <1> DP_OUT:
  2938 00001A1B E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2939                              <1> 	;XOR	AX,AX			; CLEAR
  2940                              <1> 	; 24/12/2021
  2941 00001A20 31C0                <1> 	xor	eax, eax
  2942 00001A22 F8                  <1> 	CLC
  2943 00001A23 C3                  <1> 	RETn
  2944                              <1> 
  2945                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2946                              <1> 
  2947                              <1> NON_DRV:
  2948                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2949 00001A24 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2950                              <1> NON_DRV1:
  2951 00001A27 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2952 00001A2C 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2953                              <1> 
  2954                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2955                              <1> 	
  2956 00001A2E E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2957                              <1> 	;MOV	AX,SI			; RESTORE AL
  2958 00001A33 89F0                <1> 	mov	eax, esi ; 24/12/2021
  2959 00001A35 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2960 00001A37 F9                  <1> 	STC
  2961 00001A38 C3                  <1> 	RETn
  2962                              <1> 
  2963                              <1> NON_DRV2:
  2964                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2965 00001A39 31C0                <1> 	xor	eax, eax	
  2966 00001A3B 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2967                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2968 00001A3F 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2969                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2970 00001A42 89450C              <1> 	mov	[ebp+12], eax
  2971                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2972 00001A45 EBD4                <1> 	JMP	SHORT DP_OUT
  2973                              <1> 
  2974                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2975                              <1> 
  2976                              <1> USE_EST2:
  2977 00001A47 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2978 00001A49 E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2979 00001A4E 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2980 00001A51 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2981 00001A54 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2982 00001A57 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2983 00001A59 EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2984                              <1> 
  2985                              <1> ;-------------------------------------------------------------------------------
  2986                              <1> ; DISK_TYPE (AH = 15H)	
  2987                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2988                              <1> ;
  2989                              <1> ;  ON ENTRY:	DI = DRIVE #
  2990                              <1> ;
  2991                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2992                              <1> ;-------------------------------------------------------------------------------
  2993                              <1> DSK_TYPE:
  2994 00001A5B E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2995 00001A60 8A87[296C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2996 00001A66 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2997 00001A68 7415                <1> 	JZ	short NO_DRV
  2998 00001A6A B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  2999 00001A6C A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3000 00001A6E 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3001 00001A70 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3002                              <1> DT_BACK:
  3003                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3004 00001A72 50                  <1> 	push	eax ; 24/12/2021
  3005 00001A73 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3006                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3007 00001A78 58                  <1> 	pop	eax ; 24/12/2021
  3008 00001A79 F8                  <1> 	CLC				; NO ERROR
  3009                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3010                              <1> 	; 24/12/2021
  3011 00001A7A 89F3                <1> 	mov	ebx, esi
  3012 00001A7C 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3013 00001A7E C3                  <1> 	RETn
  3014                              <1> NO_DRV:	
  3015 00001A7F 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3016 00001A81 EBEF                <1> 	JMP	SHORT DT_BACK
  3017                              <1> 
  3018                              <1> ;-------------------------------------------------------------------------------
  3019                              <1> ; DISK_CHANGE	(AH = 16H)
  3020                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3021                              <1> ;
  3022                              <1> ; ON ENTRY:	DI = DRIVE #
  3023                              <1> ;
  3024                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3025                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3026                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3027                              <1> ;-------------------------------------------------------------------------------
  3028                              <1> DSK_CHANGE:
  3029 00001A83 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3030 00001A88 8A87[296C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3031 00001A8E 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3032 00001A90 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3033 00001A92 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3034 00001A94 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3035                              <1> DC0:
  3036 00001A96 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3037 00001A9B 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3038                              <1> 
  3039 00001A9D C605[1C6C0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3040                              <1> 
  3041 00001AA4 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3042 00001AA9 E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3043                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3044                              <1> 	; 24/12/2021
  3045 00001AAE 89F3                <1> 	mov	ebx, esi
  3046 00001AB0 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3047 00001AB2 C3                  <1> 	RETn
  3048                              <1> DC_NON:
  3049 00001AB3 800D[1C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3050 00001ABA EBE8                <1> 	JMP	SHORT FINIS
  3051                              <1> 
  3052                              <1> ;-------------------------------------------------------------------------------
  3053                              <1> ; FORMAT_SET	(AH = 17H)
  3054                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3055                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3056                              <1> ;
  3057                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3058                              <1> ;		DI     = DRIVE #
  3059                              <1> ;
  3060                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3061                              <1> ;		AH = @DSKETTE_STATUS
  3062                              <1> ;		CY = 1 IF ERROR
  3063                              <1> ;-------------------------------------------------------------------------------
  3064                              <1> FORMAT_SET:
  3065 00001ABC E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3066                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3067                              <1> 	; 24/12/2021
  3068 00001AC1 56                  <1> 	push	esi
  3069 00001AC2 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3070 00001AC5 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3071 00001AC7 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3072 00001ACA 80A7[296C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3073 00001AD1 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3074 00001AD3 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3075 00001AD5 808F[296C0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3076 00001ADC EB48                <1> 	JMP	SHORT S0
  3077                              <1> NOT_320:
  3078 00001ADE E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3079 00001AE3 803D[1C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3080 00001AEA 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3081                              <1> S3:
  3082 00001AEC 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3083 00001AEE 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3084 00001AF0 808F[296C0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3085 00001AF7 EB2D                <1> 	JMP	SHORT S0
  3086                              <1> NOT_320_12:
  3087 00001AF9 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3088 00001AFB 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3089 00001AFD 808F[296C0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3090 00001B04 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3091                              <1> NOT_12:	
  3092 00001B06 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3093 00001B08 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3094                              <1> 
  3095 00001B0A F687[296C0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3096 00001B11 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3097 00001B13 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3098 00001B15 F687[296C0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3099 00001B1C 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3100                              <1> ASSUME:
  3101 00001B1E B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3102                              <1> OR_IT_IN:
  3103 00001B20 0887[296C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3104                              <1> S0:
  3105 00001B26 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3106 00001B2B E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3107                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3108                              <1> 	; 24/12/2021
  3109 00001B30 5B                  <1> 	pop	ebx
  3110 00001B31 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3111 00001B33 C3                  <1> 	RETn
  3112                              <1> FS_ERR:
  3113 00001B34 C605[1C6C0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3114 00001B3B EBE9                <1> 	JMP	SHORT S0
  3115                              <1> 
  3116                              <1> ;-------------------------------------------------------------------------------
  3117                              <1> ; SET_MEDIA	(AH = 18H)
  3118                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3119                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3120                              <1> ;
  3121                              <1> ; ON ENTRY:
  3122                              <1> ;	[BP]	= SECTOR PER TRACK
  3123                              <1> ;	[BP+1]	= TRACK #
  3124                              <1> ;	DI	= DRIVE #
  3125                              <1> ;
  3126                              <1> ; ON EXIT:
  3127                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3128                              <1> ;	IF NO ERROR:
  3129                              <1> ;		AH = 0
  3130                              <1> ;		CY = 0
  3131                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3132                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3133                              <1> ;	IF ERROR:	
  3134                              <1> ;		AH = @DSKETTE_STATUS
  3135                              <1> ;		CY = 1
  3136                              <1> ;-------------------------------------------------------------------------------
  3137                              <1> SET_MEDIA:
  3138 00001B3D E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3139 00001B42 F687[296C0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3140 00001B49 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3141 00001B4B E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3142 00001B50 803D[1C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3143 00001B57 746B                <1> 	JE	short SM_RTN
  3144 00001B59 C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3145                              <1> SM_CMOS:
  3146 00001B60 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3147                              <1> 	;;20/02/2015
  3148                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3149                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3150 00001B65 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3151 00001B67 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3152 00001B6C 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3153 00001B6E 57                  <1> 	PUSH	eDI			; SAVE REG.
  3154 00001B6F 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3155 00001B71 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3156                              <1> DR_SEARCH:
  3157 00001B76 8AA3[0C660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3158 00001B7C 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3159 00001B7F 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3160 00001B81 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3161                              <1> DR_FND:
  3162 00001B83 8BBB[0D660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3163                              <1> MD_SEARCH:
  3164 00001B89 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3165 00001B8C 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3166 00001B8F 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3167 00001B91 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3168 00001B94 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3169 00001B97 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3170                              <1> NXT_MD:
  3171                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3172 00001B99 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3173 00001B9C E2D8                <1> 	LOOP    DR_SEARCH
  3174 00001B9E 5F                  <1> 	POP	eDI			; RESTORE REG.
  3175                              <1> MD_NOT_FND:
  3176 00001B9F C605[1C6C0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3177 00001BA6 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3178                              <1> MD_FND:
  3179 00001BA8 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3180 00001BAB 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3181 00001BAD 7502                <1> 	JNE	short MD_SET
  3182 00001BAF 0C20                <1> 	OR	AL,DBL_STEP
  3183                              <1> MD_SET:
  3184                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3185 00001BB1 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3186 00001BB4 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3187 00001BB6 5F                  <1> 	POP	eDI
  3188 00001BB7 80A7[296C0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3189 00001BBE 0887[296C0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3190                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3191                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3192                              <1> SM_RTN:
  3193 00001BC4 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3194 00001BC9 E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3195 00001BCE C3                  <1> 	RETn
  3196                              <1> 
  3197                              <1> ;----------------------------------------------------------------
  3198                              <1> ; DR_TYPE_CHECK							:
  3199                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3200                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3201                              <1> ; ON ENTRY:							:
  3202                              <1> ;	AL = DRIVE TYPE						:
  3203                              <1> ; ON EXIT:							:
  3204                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3205                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3206                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3207                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3208                              <1> ; REGISTERS ALTERED: eBX						:
  3209                              <1> ;----------------------------------------------------------------		
  3210                              <1> DR_TYPE_CHECK:
  3211                              <1> 	;PUSH	AX			
  3212                              <1> 	; 24/12/2021
  3213 00001BCF 50                  <1> 	push	eax
  3214 00001BD0 51                  <1> 	PUSH	eCX
  3215 00001BD1 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3216 00001BD3 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3217                              <1> TYPE_CHK:	
  3218 00001BD8 8AA3[0C660000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3219 00001BDE 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3220 00001BE0 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3221                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3222 00001BE2 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3223 00001BE5 E2F1                <1> 	LOOP    TYPE_CHK
  3224                              <1> 	;
  3225 00001BE7 BB[6B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3226                              <1> 					; Default for GET_PARM (11/12/2014)
  3227                              <1> 	;
  3228 00001BEC F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3229 00001BED EB06                <1> 	JMP	SHORT TYPE_RTN
  3230                              <1> DR_TYPE_VALID:
  3231 00001BEF 8B9B[0D660000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3232                              <1> TYPE_RTN:
  3233 00001BF5 59                  <1> 	POP	eCX
  3234                              <1> 	;POP	AX
  3235                              <1> 	; 24/12/2021
  3236 00001BF6 58                  <1> 	pop	eax
  3237 00001BF7 C3                  <1> 	RETn	
  3238                              <1> 		
  3239                              <1> ;----------------------------------------------------------------
  3240                              <1> ; SEND_SPEC							:
  3241                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3242                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3243                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3244                              <1> ; ON EXIT:	NONE						:	
  3245                              <1> ; REGISTERS ALTERED: CX, DX					:
  3246                              <1> ;----------------------------------------------------------------		
  3247                              <1> SEND_SPEC:
  3248 00001BF8 50                  <1> 	PUSH	eAX			; SAVE AX
  3249 00001BF9 B8[1F1C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3250 00001BFE 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3251 00001BFF B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3252 00001C01 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3253 00001C06 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3254 00001C08 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3255 00001C0D E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3256 00001C12 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3257 00001C14 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3258 00001C19 E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3259 00001C1E 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3260                              <1> SPECBAC:
  3261 00001C1F 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3262 00001C20 C3                  <1> 	RETn
  3263                              <1> 
  3264                              <1> ;----------------------------------------------------------------
  3265                              <1> ; SEND_SPEC_MD							:
  3266                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3267                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3268                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3269                              <1> ; ON EXIT:	NONE						:	
  3270                              <1> ; REGISTERS ALTERED: AX						:
  3271                              <1> ;----------------------------------------------------------------		
  3272                              <1> SEND_SPEC_MD:
  3273 00001C21 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3274 00001C22 B8[3F1C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3275 00001C27 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3276 00001C28 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3277 00001C2A E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3278 00001C2F 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3279 00001C31 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3280 00001C36 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3281 00001C39 E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3282 00001C3E 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3283                              <1> SPEC_ESBAC:
  3284 00001C3F 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3285 00001C40 C3                  <1> 	RETn
  3286                              <1> 
  3287                              <1> ;-------------------------------------------------------------------------------
  3288                              <1> ; XLAT_NEW  
  3289                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3290                              <1> ;	MODE TO NEW ARCHITECTURE.
  3291                              <1> ;
  3292                              <1> ; ON ENTRY:	DI = DRIVE #
  3293                              <1> ;-------------------------------------------------------------------------------
  3294                              <1> XLAT_NEW:
  3295 00001C41 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3296 00001C44 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3297 00001C46 80BF[296C0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3298 00001C4D 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3299 00001C4F 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3300 00001C52 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3301 00001C55 A0[286C0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3302 00001C5A D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3303 00001C5C 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3304 00001C5E 80A7[296C0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3305 00001C65 0887[296C0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3306                              <1> XN_OUT:
  3307 00001C6B C3                  <1> 	RETn
  3308                              <1> DO_DET:
  3309 00001C6C E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3310 00001C71 C3                  <1> 	RETn
  3311                              <1> 
  3312                              <1> ;-------------------------------------------------------------------------------
  3313                              <1> ; XLAT_OLD 
  3314                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3315                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3316                              <1> ;
  3317                              <1> ; ON ENTRY:	DI = DRIVE
  3318                              <1> ;-------------------------------------------------------------------------------
  3319                              <1> XLAT_OLD:
  3320 00001C72 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3321                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3322                              <1>         ;ja	XO_OUT
  3323                              <1>         ; 24/12/2021
  3324 00001C75 77F4                <1> 	ja	short XN_OUT
  3325 00001C77 80BF[296C0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3326 00001C7E 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3327                              <1> 
  3328                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3329                              <1> 
  3330 00001C80 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3331 00001C83 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3332 00001C86 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3333 00001C88 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3334 00001C8A 8425[286C0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3335 00001C90 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3336                              <1> 
  3337                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3338                              <1> 
  3339 00001C92 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3340 00001C94 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3341 00001C96 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3342 00001C98 2025[286C0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3343                              <1> 
  3344                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3345                              <1> 
  3346 00001C9E 8A87[296C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3347 00001CA4 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3348 00001CA6 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3349 00001CA8 0805[286C0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3350                              <1> 
  3351                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3352                              <1> 
  3353                              <1> SAVE_SET:
  3354 00001CAE 8AA7[296C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3355 00001CB4 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3356 00001CB6 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3357 00001CB9 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3358 00001CBC 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3359 00001CBE B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3360 00001CC0 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3361 00001CC3 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3362 00001CC5 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3363 00001CC8 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3364                              <1> UNKNO:
  3365 00001CCA B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3366 00001CCC EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3367                              <1> CHK_144:
  3368 00001CCE E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3369                              <1> 	;;20/02/2015
  3370                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3371 00001CD3 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3372 00001CD5 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3373 00001CD7 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3374 00001CD9 B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3375 00001CDB EB0C                <1> 	JMP	SHORT TST_DET
  3376                              <1> CHK_250:
  3377 00001CDD B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3378 00001CDF 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3379 00001CE2 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3380 00001CE4 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3381 00001CE7 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3382                              <1> TST_DET:
  3383 00001CE9 F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3384 00001CEC 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3385 00001CEE 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3386                              <1> AL_SET:
  3387 00001CF0 80A7[296C0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3388 00001CF7 0887[296C0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3389                              <1> XO_OUT:
  3390 00001CFD C3                  <1> 	RETn
  3391                              <1> 
  3392                              <1> ;-------------------------------------------------------------------------------
  3393                              <1> ; RD_WR_VF
  3394                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3395                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3396                              <1> ;
  3397                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3398                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3399                              <1> ;
  3400                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3401                              <1> ;-------------------------------------------------------------------------------
  3402                              <1> RD_WR_VF:
  3403                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3404 00001CFE 50                  <1> 	push	eax ; 24/12/2021
  3405 00001CFF E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3406 00001D04 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3407                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3408 00001D09 58                  <1> 	pop	eax ; 24/12/2021
  3409                              <1> DO_AGAIN:
  3410                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3411 00001D0A 50                  <1> 	push	eax ; 24/12/2021
  3412 00001D0B E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3413                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3414 00001D10 58                  <1> 	pop	eax ; 24/12/2021
  3415                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3416                              <1> 	; 24/12/2021
  3417 00001D11 7305                <1> 	jnc	short RWV
  3418 00001D13 E9C3000000          <1> 	jmp	RWV_END
  3419                              <1> RWV:
  3420                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3421 00001D18 50                  <1> 	push	eax ; 24/12/2021
  3422 00001D19 8AB7[296C0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3423 00001D1F 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3424 00001D22 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3425                              <1> 	;;20/02/2015
  3426                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3427 00001D27 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3428 00001D29 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3429 00001D2B 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3430 00001D2D F687[296C0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3431 00001D34 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3432 00001D36 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3433 00001D38 EB0F                <1> 	JMP	SHORT RWV_2
  3434                              <1> RWV_1:
  3435 00001D3A 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3436 00001D3C F687[296C0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3437 00001D43 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3438 00001D45 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3439 00001D47 EB04                <1> 	jmp	short rwv_3
  3440                              <1> RWV_2:
  3441 00001D49 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3442 00001D4B 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3443                              <1> rwv_3:
  3444 00001D4D E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3445 00001D52 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3446                              <1> 
  3447                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3448                              <1> 
  3449 00001D54 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3450 00001D55 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3451 00001D57 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3452                              <1> RWV_DR_SEARCH:
  3453 00001D5C 8AA3[0C660000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3454 00001D62 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3455 00001D65 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3456 00001D67 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3457                              <1> RWV_DR_FND:
  3458 00001D69 8BBB[0D660000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3459                              <1> RWV_MD_SEARH:
  3460 00001D6F 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3461 00001D72 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3462                              <1> RWV_NXT_MD:
  3463                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3464 00001D74 83C305              <1> 	add	eBX, 5
  3465 00001D77 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3466 00001D79 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3467                              <1> 
  3468                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3469                              <1> 
  3470                              <1> RWV_ASSUME:
  3471 00001D7A BB[2A660000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3472 00001D7F F687[296C0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3473 00001D86 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3474 00001D88 BB[44660000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3475 00001D8D EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3476                              <1> 
  3477                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3478                              <1> 	 			
  3479                              <1> RWV_MD_FND:
  3480 00001D8F 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3481 00001D91 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3482                              <1> 	
  3483                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3484                              <1> 
  3485                              <1> RWV_MD_FND1:
  3486 00001D92 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3487 00001D97 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3488 00001D9C 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3489 00001D9E E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3490                              <1> RWV_DBL:
  3491 00001DA3 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3492 00001DA4 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3493 00001DA9 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3494 00001DAA 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3495                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3496 00001DAC 58                  <1> 	pop	eax ; 24/12/2021
  3497                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3498 00001DAD 50                  <1> 	push	eax ; 24/12/2021
  3499 00001DAE 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3500 00001DAF E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3501 00001DB4 5B                  <1> 	POP	eBX 
  3502                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3503 00001DB5 58                  <1> 	pop	eax ; 24/12/2021
  3504 00001DB6 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3505                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3506 00001DB8 50                  <1> 	push	eax ; 24/12/2021
  3507 00001DB9 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3508 00001DBA E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3509 00001DBF 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3510 00001DC0 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3511 00001DC2 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3512 00001DC7 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3513 00001DC9 E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3514                              <1> CHK_RET:
  3515 00001DCE E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3516                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3517 00001DD3 58                  <1> 	pop	eax ; 24/12/2021
  3518 00001DD4 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3519 00001DD6 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3520                              <1> RWV_END:
  3521 00001DDB E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3522 00001DE0 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3523                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3524                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3525 00001DE5 50                  <1> 	push	eax ; 24/12/2021
  3526 00001DE6 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3527                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3528 00001DEB 58                  <1> 	pop	eax ; 24/12/2021
  3529 00001DEC E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3530 00001DF1 C3                  <1> 	RETn
  3531                              <1> 
  3532                              <1> ;-------------------------------------------------------------------------------
  3533                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3534                              <1> ;-------------------------------------------------------------------------------
  3535                              <1> SETUP_STATE:
  3536 00001DF2 F687[296C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3537 00001DF9 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3538 00001DFB 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3539 00001DFF F687[296C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3540 00001E06 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3541 00001E08 F687[296C0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3542 00001E0F 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3543 00001E11 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3544                              <1> AX_SET:	
  3545 00001E15 80A7[296C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3546 00001E1C 08A7[296C0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3547 00001E22 8025[246C0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3548 00001E29 C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3549 00001E2C 0805[246C0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3550                              <1> J1C:	
  3551 00001E32 C3                  <1> 	RETn
  3552                              <1> 
  3553                              <1> ;-------------------------------------------------------------------------------
  3554                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3555                              <1> ;-------------------------------------------------------------------------------
  3556                              <1> FMT_INIT:
  3557 00001E33 F687[296C0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3558 00001E3A 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3559 00001E3C E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3560                              <1> 	;; 20/02/2015
  3561                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3562 00001E41 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3563 00001E43 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3564                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3565 00001E45 8AA7[296C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3566 00001E4B 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3567 00001E4E 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3568 00001E50 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3569 00001E52 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3570 00001E55 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3571                              <1> N_360:	
  3572 00001E57 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3573 00001E59 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3574                              <1> F1_RATE:
  3575 00001E5B 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3576 00001E5E EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3577                              <1> N_12:	
  3578 00001E60 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3579 00001E62 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3580 00001E64 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3581 00001E67 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3582 00001E69 F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3583 00001E6C 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3584 00001E6E 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3585 00001E71 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3586                              <1> N_720:
  3587 00001E73 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3588 00001E75 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3589 00001E77 EBE2                <1> 	JMP	SHORT F1_RATE
  3590                              <1> ISNT_12: 
  3591 00001E79 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3592                              <1> 
  3593                              <1> SKP_STATE:
  3594 00001E7C 88A7[296C0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3595                              <1> F1_OUT:
  3596 00001E82 C3                  <1> 	RETn
  3597                              <1> CL_DRV:	
  3598 00001E83 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3599 00001E85 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3600                              <1> 
  3601                              <1> ;-------------------------------------------------------------------------------
  3602                              <1> ; MED_CHANGE	
  3603                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3604                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3605                              <1> ;
  3606                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3607                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3608                              <1> ;-------------------------------------------------------------------------------
  3609                              <1> MED_CHANGE:
  3610 00001E87 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3611 00001E8C 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3612 00001E8E 80A7[296C0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3613                              <1> 
  3614                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3615                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3616                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3617                              <1> 
  3618 00001E95 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3619 00001E98 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3620 00001E9A D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3621 00001E9C F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3622 00001E9E FA                  <1> 	CLI				; NO INTERRUPTS
  3623 00001E9F 2005[1A6C0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3624 00001EA5 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3625 00001EA6 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3626                              <1> 
  3627                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3628                              <1> 
  3629 00001EAB E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3630 00001EB0 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3631 00001EB2 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3632 00001EB7 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3633 00001EB9 E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3634 00001EBE C605[1C6C0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3635                              <1> OK1:
  3636 00001EC5 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3637 00001ECA 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3638                              <1> OK4:
  3639 00001ECC C605[1C6C0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3640                              <1> OK2:		
  3641 00001ED3 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3642 00001ED4 C3                  <1> 	RETn
  3643                              <1> MC_OUT:
  3644 00001ED5 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3645 00001ED6 C3                  <1> 	RETn
  3646                              <1> 
  3647                              <1> ;-------------------------------------------------------------------------------
  3648                              <1> ; SEND_RATE
  3649                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3650                              <1> ; ON ENTRY:	DI = DRIVE #
  3651                              <1> ; ON EXIT:	NONE
  3652                              <1> ; REGISTERS ALTERED: DX
  3653                              <1> ;-------------------------------------------------------------------------------
  3654                              <1> SEND_RATE:
  3655                              <1> 	;PUSH	AX			; SAVE REG.
  3656                              <1> 	; 24/12/2021
  3657 00001ED7 50                  <1> 	push	eax
  3658 00001ED8 8025[246C0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3659 00001EDF 8A87[296C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3660 00001EE5 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3661 00001EE7 0805[246C0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3662 00001EED C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3663 00001EF0 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3664 00001EF4 EE                  <1> 	OUT	DX,AL
  3665                              <1> 	;POP	AX			; RESTORE REG.
  3666                              <1> 	; 24/12/2021
  3667 00001EF5 58                  <1> 	pop	eax
  3668 00001EF6 C3                  <1> 	RETn
  3669                              <1> 
  3670                              <1> ;-------------------------------------------------------------------------------
  3671                              <1> ; CHK_LASTRATE
  3672                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3673                              <1> ; ON ENTRY:
  3674                              <1> ;	DI = DRIVE #
  3675                              <1> ; ON EXIT:
  3676                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3677                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3678                              <1> ; REGISTERS ALTERED: DX
  3679                              <1> ;-------------------------------------------------------------------------------
  3680                              <1> CHK_LASTRATE:
  3681                              <1> 	;PUSH	AX			; SAVE REG.
  3682                              <1> 	; 24/12/2021
  3683 00001EF7 50                  <1> 	push	eax
  3684 00001EF8 2225[246C0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3685 00001EFE 8A87[296C0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3686 00001F04 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3687 00001F08 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3688                              <1> 					; ZF = 1 RATE IS THE SAME
  3689                              <1> 	;POP	AX			; RESTORE REG.
  3690                              <1> 	; 24/12/2021
  3691 00001F0A 58                  <1> 	pop	eax
  3692 00001F0B C3                  <1> 	RETn
  3693                              <1> 
  3694                              <1> ;-------------------------------------------------------------------------------
  3695                              <1> ; DMA_SETUP
  3696                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3697                              <1> ;
  3698                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3699                              <1> ;
  3700                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3701                              <1> ;-------------------------------------------------------------------------------
  3702                              <1> 
  3703                              <1> ; SI = Head #, # of Sectors or DASD Type
  3704                              <1> 
  3705                              <1> ; 22/08/2015
  3706                              <1> ; 08/02/2015 - Protected Mode Modification
  3707                              <1> ; 06/02/2015 - 07/02/2015
  3708                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3709                              <1> ; (DMA Addres = Physical Address)
  3710                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3711                              <1> ;
  3712                              <1> ; 04/02/2016 (clc)
  3713                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3714                              <1> ; 16/12/2014 (IODELAY)
  3715                              <1> 
  3716                              <1> DMA_SETUP:
  3717                              <1> 
  3718                              <1> ;; 20/02/2015
  3719 00001F0C 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3720 00001F0F F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3721 00001F15 7569                <1> 	jnz	short dma_bnd_err_stc
  3722                              <1> 	;
  3723                              <1> 	;push	ax			; DMA command
  3724                              <1> 	; 24/12/2021
  3725 00001F17 50                  <1> 	push	eax
  3726 00001F18 52                  <1> 	push	edx			; *
  3727 00001F19 B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3728 00001F1B E840030000          <1> 	call	GET_PARM		; 
  3729 00001F20 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3730                              <1> 	;mov	ax, si			; Sector count
  3731                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3732                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3733                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3734                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3735                              <1> 	; 24/12/2021
  3736 00001F22 89F2                <1> 	mov	edx, esi
  3737 00001F24 29C0                <1> 	sub	eax, eax
  3738 00001F26 88D4                <1> 	mov	ah, dl
  3739 00001F28 D1E8                <1> 	shr	eax, 1
  3740 00001F2A D3E0                <1> 	shl	eax, cl
  3741                              <1> 	;
  3742 00001F2C 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3743 00001F2E 6689C1              <1> 	mov	cx, ax
  3744 00001F31 5A                  <1> 	pop	edx			; *
  3745                              <1> 	;pop	ax
  3746                              <1> 	; 24/12/2021
  3747 00001F32 58                  <1> 	pop	eax
  3748 00001F33 3C42                <1> 	cmp	al, 42h
  3749 00001F35 7507                <1>         jne     short NOT_VERF
  3750 00001F37 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3751 00001F3C EB08                <1> 	jmp	short J33
  3752                              <1> NOT_VERF:
  3753 00001F3E 6601CA              <1> 	add	dx, cx			; check for overflow
  3754 00001F41 723E                <1> 	jc	short dma_bnd_err
  3755                              <1> 	;
  3756 00001F43 6629CA              <1> 	sub	dx, cx			; Restore start address
  3757                              <1> J33:
  3758 00001F46 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3759 00001F47 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3760                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001F49 EB00                <2>  jmp short $+2
  2103 00001F4B EB00                <2>  jmp short $+2
  3761 00001F4D E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3762 00001F4F 89D0                <1> 	mov	eax,edx			; Buffer address
  3763 00001F51 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3764                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001F53 EB00                <2>  jmp short $+2
  2103 00001F55 EB00                <2>  jmp short $+2
  3765 00001F57 88E0                <1> 	MOV	AL,AH
  3766 00001F59 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3767 00001F5B C1E810              <1> 	shr	eax,16
  3768                              <1> 	IODELAY				; I/O WAIT STATE
  2102 00001F5E EB00                <2>  jmp short $+2
  2103 00001F60 EB00                <2>  jmp short $+2
  3769 00001F62 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3770                              <1> 	IODELAY
  2102 00001F64 EB00                <2>  jmp short $+2
  2103 00001F66 EB00                <2>  jmp short $+2
  3771 00001F68 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3772 00001F6B E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3773                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001F6D EB00                <2>  jmp short $+2
  2103 00001F6F EB00                <2>  jmp short $+2
  3774 00001F71 88E0                <1> 	MOV	AL,AH
  3775 00001F73 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3776                              <1> 	IODELAY
  2102 00001F75 EB00                <2>  jmp short $+2
  2103 00001F77 EB00                <2>  jmp short $+2
  3777 00001F79 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3778 00001F7A B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3779 00001F7C E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3780                              <1> 
  3781 00001F7E F8                  <1> 	clc	; 04/02/2016
  3782 00001F7F C3                  <1> 	retn
  3783                              <1> 
  3784                              <1> dma_bnd_err_stc:
  3785 00001F80 F9                  <1> 	stc
  3786                              <1> dma_bnd_err:
  3787 00001F81 C605[1C6C0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3788 00001F88 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3789                              <1> 
  3790                              <1> ;; 16/12/2014
  3791                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3792                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3793                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3794                              <1> ;;	IODELAY
  3795                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3796                              <1> ;;	;SIODELAY
  3797                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3798                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3799                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3800                              <1> ;;      ;JMP	SHORT J33
  3801                              <1> ;;;NOT_VERF:	
  3802                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3803                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3804                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3805                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3806                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3807                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3808                              <1> ;;	;JNC	short J33
  3809                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3810                              <1> ;;;J33:
  3811                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3812                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3813                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3814                              <1> ;;	IODELAY
  3815                              <1> ;;	MOV	AL,AH
  3816                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3817                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3818                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3819                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3820                              <1> ;;	IODELAY
  3821                              <1> ;;	;AND	AL,00001111B
  3822                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3823                              <1> ;;	;SIODELAY
  3824                              <1> ;;
  3825                              <1> ;;;----- DETERMINE COUNT
  3826                              <1> ;;	sub	eax, eax ; 08/02/2015
  3827                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3828                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3829                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3830                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3831                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3832                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3833                              <1> ;;	CALL	GET_PARM		; "
  3834                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3835                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3836                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3837                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3838                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3839                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3840                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3841                              <1> ;;	IODELAY
  3842                              <1> ;;	MOV	AL, AH
  3843                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3844                              <1> ;;	;IODELAY
  3845                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3846                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3847                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3848                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3849                              <1> ;;	add	ecx, eax ; 08/02/2015
  3850                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3851                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3852                              <1> ;;	SIODELAY
  3853                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3854                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3855                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3856                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3857                              <1> ;;	jz	short NO_BAD
  3858                              <1> ;;dma_bnd_err:
  3859                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3860                              <1> ;;NO_BAD:
  3861                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3862                              <1> 
  3863                              <1> ;-------------------------------------------------------------------------------
  3864                              <1> ; FMTDMA_SET
  3865                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3866                              <1> ;
  3867                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3868                              <1> ;
  3869                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3870                              <1> ;-------------------------------------------------------------------------------
  3871                              <1> 
  3872                              <1> 	; 24/12/2021
  3873                              <1> FMTDMA_SET:
  3874                              <1> ;; 20/02/2015 modification	
  3875 00001F89 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3876 00001F8C F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3877 00001F92 75EC                <1> 	jnz	short dma_bnd_err_stc
  3878                              <1> 	;
  3879                              <1> 	;push	dx			; *
  3880                              <1> 	; 24/12/2021
  3881 00001F94 52                  <1> 	push	edx
  3882 00001F95 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3883 00001F97 E8C4020000          <1> 	call	GET_PARM		; "
  3884                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3885                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3886                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3887                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3888                              <1> 	;mov	cx, ax
  3889                              <1> 	; 24/12/2021
  3890 00001F9C 29C9                <1> 	sub	ecx, ecx
  3891 00001F9E 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3892 00001FA0 D1E1                <1> 	shl	ecx, 1
  3893 00001FA2 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3894 00001FA4 6649                <1> 	dec	cx
  3895                              <1> 	;pop	dx			; *
  3896                              <1> 	; 24/12/2021
  3897 00001FA6 5A                  <1> 	pop	edx
  3898 00001FA7 6601CA              <1> 	add	dx, cx			; check for overflow
  3899 00001FAA 72D5                <1> 	jc	short dma_bnd_err
  3900                              <1> 	;
  3901 00001FAC 6629CA              <1> 	sub	dx, cx			; Restore start address
  3902                              <1> 	;
  3903 00001FAF B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3904 00001FB1 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3905 00001FB2 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3906                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001FB4 EB00                <2>  jmp short $+2
  2103 00001FB6 EB00                <2>  jmp short $+2
  3907 00001FB8 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3908 00001FBA 89D0                <1> 	mov	eax,edx			; Buffer address
  3909 00001FBC E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3910                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001FBE EB00                <2>  jmp short $+2
  2103 00001FC0 EB00                <2>  jmp short $+2
  3911 00001FC2 88E0                <1> 	MOV	AL,AH
  3912 00001FC4 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3913 00001FC6 C1E810              <1> 	shr	eax,16
  3914                              <1> 	IODELAY				; I/O WAIT STATE
  2102 00001FC9 EB00                <2>  jmp short $+2
  2103 00001FCB EB00                <2>  jmp short $+2
  3915 00001FCD E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3916                              <1> 	IODELAY
  2102 00001FCF EB00                <2>  jmp short $+2
  2103 00001FD1 EB00                <2>  jmp short $+2
  3917 00001FD3 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3918 00001FD6 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3919                              <1> 	IODELAY				; WAIT FOR I/O
  2102 00001FD8 EB00                <2>  jmp short $+2
  2103 00001FDA EB00                <2>  jmp short $+2
  3920 00001FDC 88E0                <1> 	MOV	AL,AH
  3921 00001FDE E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3922                              <1> 	IODELAY
  2102 00001FE0 EB00                <2>  jmp short $+2
  2103 00001FE2 EB00                <2>  jmp short $+2
  3923 00001FE4 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3924 00001FE5 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3925 00001FE7 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3926 00001FE9 C3                  <1> 	retn
  3927                              <1> 
  3928                              <1> ;; 08/02/2015 - Protected Mode Modification
  3929                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3930                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3931                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3932                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3933                              <1> ;;	IODELAY
  3934                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3935                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3936                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3937                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3938                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3939                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3940                              <1> ;;	;JNC	short J33A
  3941                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3942                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3943                              <1> ;;;J33A:
  3944                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3945                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3946                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3947                              <1> ;;	IODELAY
  3948                              <1> ;;	MOV	AL,AH
  3949                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3950                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3951                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3952                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3953                              <1> ;;	IODELAY
  3954                              <1> ;;	;AND	AL,00001111B
  3955                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3956                              <1> ;;
  3957                              <1> ;;;----- DETERMINE COUNT
  3958                              <1> ;;	sub	eax, eax ; 08/02/2015
  3959                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3960                              <1> ;;	CALL	GET_PARM		; "
  3961                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3962                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3963                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3964                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3965                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3966                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3967                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3968                              <1> ;;	IODELAY
  3969                              <1> ;;	MOV	AL, AH
  3970                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3971                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3972                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3973                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3974                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3975                              <1> ;;	add	ecx, eax ; 08/02/2015
  3976                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3977                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3978                              <1> ;;	SIODELAY
  3979                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3980                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3981                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3982                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3983                              <1> ;;	jz	short FMTDMA_OK
  3984                              <1> ;;	stc	; 20/02/2015
  3985                              <1> ;;fmtdma_bnd_err:
  3986                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3987                              <1> ;;FMTDMA_OK:
  3988                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3989                              <1> 
  3990                              <1> ;-------------------------------------------------------------------------------
  3991                              <1> ; NEC_INIT	
  3992                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3993                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3994                              <1> ;
  3995                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3996                              <1> ;
  3997                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3998                              <1> ;-------------------------------------------------------------------------------
  3999                              <1> NEC_INIT:
  4000                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4001                              <1> 	; 24/12/2021
  4002 00001FEA 50                  <1> 	push	eax
  4003 00001FEB E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4004                              <1> 
  4005                              <1> ;-----	DO THE SEEK OPERATION
  4006                              <1> 
  4007 00001FF0 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4008 00001FF3 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4009                              <1> 	;POP	AX			; RECOVER COMMAND
  4010                              <1> 	; 24/12/2021
  4011 00001FF8 58                  <1> 	pop	eax
  4012 00001FF9 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4013 00001FFB BB[19200000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4014 00002000 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4015                              <1> 
  4016                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4017                              <1> 
  4018 00002001 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4019 00002006 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4020 00002009 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4021 0000200B C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4022 0000200E 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4023 00002011 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4024 00002013 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4025 00002018 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4026                              <1> ER_1:
  4027 00002019 C3                  <1> 	RETn
  4028                              <1> 
  4029                              <1> ;-------------------------------------------------------------------------------
  4030                              <1> ; RWV_COM
  4031                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4032                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4033                              <1> ;
  4034                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4035                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4036                              <1> ;-------------------------------------------------------------------------------
  4037                              <1> RWV_COM:
  4038 0000201A B8[65200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4039 0000201F 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4040 00002020 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4041 00002023 E83E030000          <1> 	CALL	NEC_OUTPUT
  4042 00002028 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4043 0000202B E836030000          <1> 	CALL	NEC_OUTPUT
  4044 00002030 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4045 00002033 E82E030000          <1> 	CALL	NEC_OUTPUT
  4046 00002038 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4047 0000203A E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4048 0000203F E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4049 00002044 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4050 00002046 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4051 0000204B E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4052 00002050 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4053                              <1> _R15:
  4054 00002053 E80E030000          <1> 	CALL	NEC_OUTPUT
  4055 00002058 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4056 0000205A E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4057 0000205F E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4058 00002064 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4059                              <1> ER_2:
  4060 00002065 C3                  <1> 	RETn
  4061                              <1> 
  4062                              <1> ;-------------------------------------------------------------------------------
  4063                              <1> ; NEC_TERM
  4064                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4065                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4066                              <1> ;
  4067                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4068                              <1> ;-------------------------------------------------------------------------------
  4069                              <1> NEC_TERM:
  4070                              <1> 
  4071                              <1> ;-----	LET THE OPERATION HAPPEN
  4072                              <1> 
  4073 00002066 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4074 00002067 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4075 0000206C 9C                  <1> 	PUSHFd	; 24/12/2021
  4076 0000206D E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4077 00002072 724B                <1> 	JC	short SET_END_POP
  4078 00002074 9D                  <1> 	POPFd	; 24/12/2021
  4079 00002075 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4080                              <1> 
  4081                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4082                              <1> 
  4083 00002077 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4084 00002078 BE[1D6C0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4085 0000207D AC                  <1> 	lodsb				; GET ST0
  4086 0000207E 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4087 00002080 7433                <1> 	JZ	short SET_END
  4088 00002082 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4089 00002084 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4090                              <1> 
  4091                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4092                              <1> 
  4093 00002086 AC                  <1> 	lodsb				; GET ST1
  4094 00002087 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4095 00002089 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4096 0000208B 7222                <1> 	JC	short J19
  4097 0000208D C0E002              <1> 	SAL	AL,2
  4098 00002090 B410                <1> 	MOV	AH,BAD_CRC
  4099 00002092 721B                <1> 	JC	short J19
  4100 00002094 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4101 00002096 B408                <1> 	MOV	AH,BAD_DMA
  4102 00002098 7215                <1> 	JC	short J19
  4103 0000209A C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4104 0000209D B404                <1> 	MOV	AH,RECORD_NOT_FND
  4105 0000209F 720E                <1> 	JC	short J19
  4106 000020A1 D0E0                <1> 	SAL	AL,1
  4107 000020A3 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4108 000020A5 7208                <1> 	JC	short J19
  4109 000020A7 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4110 000020A9 B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4111 000020AB 7202                <1> 	JC	short J19
  4112                              <1> 
  4113                              <1> ;----- 	NEC MUST HAVE FAILED
  4114                              <1> J18:
  4115 000020AD B420                <1> 	MOV	AH,BAD_NEC
  4116                              <1> J19:
  4117 000020AF 0825[1C6C0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4118                              <1> SET_END:
  4119 000020B5 803D[1C6C0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4120 000020BC F5                  <1> 	CMC
  4121 000020BD 5E                  <1> 	POP	eSI
  4122 000020BE C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4123                              <1> 
  4124                              <1> SET_END_POP:
  4125 000020BF 9D                  <1> 	POPFd	; 24/12/2021
  4126 000020C0 EBF3                <1> 	JMP	SHORT SET_END
  4127                              <1> 
  4128                              <1> ;-------------------------------------------------------------------------------
  4129                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4130                              <1> ;-------------------------------------------------------------------------------
  4131                              <1> DSTATE:
  4132 000020C2 803D[1C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4133 000020C9 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4134 000020CB 808F[296C0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4135 000020D2 F687[296C0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4136 000020D9 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4137 000020DB 8A87[296C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4138 000020E1 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4139 000020E3 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4140 000020E5 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4141                              <1> 
  4142                              <1> ;----- 	CHECK IF IT IS 1.44M
  4143                              <1> 
  4144 000020E7 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4145                              <1> 	;;20/02/2015
  4146                              <1> 	;;JC	short M_12		; CMOS BAD
  4147 000020EC 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4148 000020EE 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4149 000020F0 7410                <1> 	JE	short M_12		; YES
  4150                              <1> M_720:
  4151 000020F2 80A7[296C0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4152 000020F9 808F[296C0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4153 00002100 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4154                              <1> M_12:	
  4155 00002102 808F[296C0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4156                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4157                              <1> SETBAC:
  4158 00002109 C3                  <1> 	RETn
  4159                              <1> 
  4160                              <1> ;-------------------------------------------------------------------------------
  4161                              <1> ; RETRY	
  4162                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4163                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4164                              <1> ;
  4165                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4166                              <1> ;-------------------------------------------------------------------------------
  4167                              <1> RETRY:
  4168 0000210A 803D[1C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4169 00002111 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4170 00002113 803D[1C6C0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4171 0000211A 743C                <1> 	JZ	short NO_RETRY
  4172 0000211C 8AA7[296C0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4173 00002122 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4174 00002125 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4175 00002127 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4176 0000212A 8A2D[246C0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4177 00002130 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4178 00002133 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4179 00002136 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4180 00002138 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4181                              <1> 
  4182                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4183                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4184                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4185                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4186                              <1> 
  4187 0000213A 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4188 0000213D D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4189 0000213F 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4190 00002142 80A7[296C0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4191                              <1> 					; RATE, DBL STEP OFF
  4192 00002149 08A7[296C0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4193 0000214F C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4194 00002156 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4195 00002157 C3                  <1> 	RETn				; RETRY RETURN
  4196                              <1> 
  4197                              <1> NO_RETRY:
  4198 00002158 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4199 00002159 C3                  <1> 	RETn				; NO RETRY RETURN
  4200                              <1> 
  4201                              <1> ;-------------------------------------------------------------------------------
  4202                              <1> ; NUM_TRANS
  4203                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4204                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4205                              <1> ;
  4206                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4207                              <1> ;		SI-HI  = HEAD
  4208                              <1> ;		[BP]   = START SECTOR
  4209                              <1> ;
  4210                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4211                              <1> ;-------------------------------------------------------------------------------
  4212                              <1> NUM_TRANS:
  4213 0000215A 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4214 0000215C 803D[1C6C0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4215                              <1> 	; 24/12/2021
  4216 00002163 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4217 00002165 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4218 00002167 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4219 0000216C 8A1D[226C0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4220 00002172 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4221 00002175 3A2D[216C0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4222 0000217B 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4223 0000217D 8A2D[206C0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4224 00002183 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4225 00002186 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4226 00002188 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4227                              <1> DIF_HD:
  4228 0000218A 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4229                              <1> SAME_TRK:
  4230 0000218C 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4231 0000218F 88D8                <1> 	MOV	AL,BL			; TO AL
  4232                              <1> NT_OUT:
  4233 00002191 C3                  <1> 	RETn
  4234                              <1> 
  4235                              <1> ;-------------------------------------------------------------------------------
  4236                              <1> ; SETUP_END
  4237                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4238                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4239                              <1> ;
  4240                              <1> ; ON EXIT:
  4241                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4242                              <1> ;-------------------------------------------------------------------------------
  4243                              <1> SETUP_END:
  4244 00002192 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4245                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4246 00002194 50                  <1> 	push	eax ; 24/12/2021
  4247 00002195 E8C6000000          <1> 	CALL	GET_PARM
  4248 0000219A 8825[1B6C0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4249                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4250 000021A0 58                  <1> 	pop	eax ; 24/12/2021
  4251 000021A1 8A25[1C6C0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4252 000021A7 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4253 000021A9 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4254 000021AB 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4255                              <1> NUN_ERR: 
  4256 000021AD 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4257 000021B0 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4258 000021B1 C3                  <1> 	RETn
  4259                              <1> 
  4260                              <1> ;-------------------------------------------------------------------------------
  4261                              <1> ; SETUP_DBL
  4262                              <1> ;	CHECK DOUBLE STEP.
  4263                              <1> ;
  4264                              <1> ; ON ENTRY :	DI = DRIVE
  4265                              <1> ;
  4266                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4267                              <1> ;-------------------------------------------------------------------------------
  4268                              <1> SETUP_DBL:
  4269 000021B2 8AA7[296C0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4270 000021B8 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4271 000021BB 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4272                              <1> 
  4273                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4274                              <1> 
  4275 000021BD C605[196C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4276 000021C4 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4277 000021C9 B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4278 000021CB E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4279 000021D0 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4280 000021D5 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4281                              <1> 
  4282                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4283                              <1> 
  4284 000021D7 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4285 000021DB F687[296C0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4286 000021E2 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4287 000021E4 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4288                              <1> 
  4289                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4290                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4291                              <1> ;	THEN SET DOUBLE STEP ON.
  4292                              <1> 
  4293                              <1> CNT_OK:
  4294 000021E6 C605[1B6C0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4295                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4296                              <1> 	; 24/12/2021
  4297 000021ED 51                  <1> 	push	ecx
  4298 000021EE C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4299 000021F5 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4300 000021F8 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4301 000021FA C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4302                              <1> 	;PUSH	AX			; SAVE HEAD
  4303                              <1> 	; 24/12/2021
  4304 000021FD 50                  <1> 	push	eax
  4305 000021FE E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4306                              <1> 	;POP	AX			; RESTORE HEAD
  4307                              <1> 	; 24/12/2021
  4308 00002203 58                  <1> 	pop	eax
  4309 00002204 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4310 00002207 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4311 0000220C 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4312 0000220D 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4313 00002212 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4314                              <1> 	;POP	CX			; RESTORE COUNT
  4315                              <1> 	; 24/12/2021
  4316 00002213 59                  <1> 	pop	ecx
  4317 00002214 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4318 00002216 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4319 00002218 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4320 0000221A 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4321                              <1> 
  4322                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4323                              <1> 
  4324                              <1> SD_ERR:	
  4325 0000221C F9                  <1> 	STC				; SET CARRY FOR ERROR
  4326 0000221D C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4327                              <1> 
  4328                              <1> DO_CHK:
  4329 0000221E 8A0D[206C0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4330 00002224 888F[2D6C0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4331 0000222A D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4332 0000222C 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4333 0000222E 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4334 00002230 808F[296C0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4335                              <1> NO_DBL:
  4336 00002237 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4337 00002238 C3                  <1> 	RETn
  4338                              <1> 
  4339                              <1> ;-------------------------------------------------------------------------------
  4340                              <1> ; READ_ID
  4341                              <1> ;	READ ID FUNCTION.
  4342                              <1> ;
  4343                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4344                              <1> ;
  4345                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4346                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4347                              <1> ;-------------------------------------------------------------------------------
  4348                              <1> READ_ID:
  4349 00002239 B8[56220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4350 0000223E 50                  <1> 	PUSH	eAX
  4351 0000223F B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4352 00002241 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4353 00002246 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4354 00002249 88C4                <1> 	MOV	AH,AL
  4355 0000224B E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4356 00002250 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4357 00002255 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4358                              <1> ER_3:
  4359 00002256 C3                  <1> 	RETn
  4360                              <1> 
  4361                              <1> ;-------------------------------------------------------------------------------
  4362                              <1> ; CMOS_TYPE
  4363                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4364                              <1> ;
  4365                              <1> ; ON ENTRY:	DI = DRIVE #
  4366                              <1> ;
  4367                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4368                              <1> ;-------------------------------------------------------------------------------
  4369                              <1> 
  4370                              <1> CMOS_TYPE: ; 11/12/2014
  4371 00002257 8A87[8E660000]      <1> 	mov	al, [eDI+fd0_type]
  4372 0000225D 20C0                <1> 	and 	al, al ; 18/12/2014
  4373 0000225F C3                  <1> 	retn
  4374                              <1> 
  4375                              <1> ;CMOS_TYPE:
  4376                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4377                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4378                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4379                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4380                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4381                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4382                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4383                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4384                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4385                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4386                              <1> ;TB:
  4387                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4388                              <1> ;BAD_CM:
  4389                              <1> ;	RETn				; CY, STATUS OF READ
  4390                              <1> 
  4391                              <1> ;-------------------------------------------------------------------------------
  4392                              <1> ; GET_PARM
  4393                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4394                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4395                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4396                              <1> ;	THE PARAMETER IN DL.
  4397                              <1> ;
  4398                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4399                              <1> ;
  4400                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4401                              <1> ;		AL,DH DESTROYED
  4402                              <1> ;-------------------------------------------------------------------------------
  4403                              <1> GET_PARM:
  4404                              <1> 	;PUSH	DS
  4405 00002260 56                  <1> 	PUSH	eSI
  4406                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4407                              <1>     	;MOV	DS,AX
  4408                              <1> 	;;mov	ax, cs
  4409                              <1> 	;;mov	ds, ax
  4410                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4411 00002261 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4412                              <1> 	;SUB	BH,BH			; BX = INDEX
  4413 00002263 81E3FF000000        <1> 	and	ebx, 0FFh
  4414                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4415                              <1> 	;
  4416                              <1> 	; 17/12/2014
  4417 00002269 66A1[81660000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4418 0000226F 38E0                <1> 	cmp	al, ah
  4419 00002271 7425                <1> 	je	short gpndc
  4420 00002273 A2[82660000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4421 00002278 53                  <1> 	push	ebx ; 08/02/2015
  4422 00002279 88C3                <1> 	mov	bl, al 
  4423                              <1> 	; 11/12/2014
  4424 0000227B 8A83[8E660000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4425                              <1> 	; 18/12/2014
  4426 00002281 20C0                <1> 	and	al, al
  4427 00002283 7507                <1> 	jnz	short gpdtc
  4428 00002285 BB[6B660000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4429 0000228A EB05                <1>         jmp     short gpdpu
  4430                              <1> gpdtc:	
  4431 0000228C E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4432                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4433                              <1> gpdpu:
  4434 00002291 891D[08660000]      <1> 	mov	[DISK_POINTER], ebx
  4435 00002297 5B                  <1> 	pop	ebx
  4436                              <1> gpndc:
  4437 00002298 8B35[08660000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4438 0000229E 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4439 000022A1 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4440 000022A3 5E                  <1> 	POP	eSI
  4441                              <1> 	;POP	DS
  4442 000022A4 C3                  <1> 	RETn
  4443                              <1> 
  4444                              <1> ;-------------------------------------------------------------------------------
  4445                              <1> ; MOTOR_ON
  4446                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4447                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4448                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4449                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4450                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4451                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4452                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4453                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4454                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4455                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4456                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4457                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4458                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4459                              <1> ;
  4460                              <1> ; ON ENTRY:	DI = DRIVE #
  4461                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4462                              <1> ;-------------------------------------------------------------------------------
  4463                              <1> MOTOR_ON:
  4464 000022A5 53                  <1> 	PUSH	eBX			; SAVE REG.
  4465 000022A6 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4466 000022AB 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4467 000022AD E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4468 000022B2 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4469                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4470                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4471                              <1> M_WAIT:
  4472 000022B7 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4473 000022B9 E8A2FFFFFF          <1> 	CALL	GET_PARM
  4474                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4475                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4476                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4477 000022BE 80FC08              <1> 	cmp	ah, 8
  4478                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4479 000022C1 7702                <1> 	ja	short J13
  4480                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4481 000022C3 B408                <1> 	mov	ah, 8
  4482                              <1> 
  4483                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4484                              <1> GP2:	
  4485                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4486                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4487 000022C5 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4488 000022CA E806F2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4489                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4490 000022CF FECC                <1> 	dec	ah
  4491 000022D1 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4492                              <1> MOT_IS_ON:
  4493 000022D3 5B                  <1> 	POP	eBX			; RESTORE REG.
  4494 000022D4 C3                  <1> 	RETn
  4495                              <1> 
  4496                              <1> ;-------------------------------------------------------------------------------
  4497                              <1> ; TURN_ON
  4498                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4499                              <1> ;
  4500                              <1> ; ON ENTRY:	DI = DRIVE #
  4501                              <1> ;
  4502                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4503                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4504                              <1> ;		AX,BX,CX,DX DESTROYED
  4505                              <1> ;-------------------------------------------------------------------------------
  4506                              <1> TURN_ON:
  4507 000022D5 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4508 000022D7 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4509 000022D9 C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4510 000022DC FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4511 000022DD C605[1B6C0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4512 000022E4 A0[1A6C0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4513 000022E9 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4514 000022EB B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4515 000022ED D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4516                              <1> 
  4517                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4518                              <1> ;  BL = DRIVE SELECT DESIRED
  4519                              <1> ;  AH = MOTOR ON MASK DESIRED
  4520                              <1> 
  4521 000022EF 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4522 000022F1 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4523 000022F3 8425[1A6C0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4524 000022F9 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4525                              <1> 
  4526                              <1> TURN_IT_ON:
  4527 000022FB 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4528 000022FD 8A3D[1A6C0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4529 00002303 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4530 00002306 8025[1A6C0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4531 0000230D 0825[1A6C0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4532 00002313 A0[1A6C0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4533 00002318 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4534 0000231A 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4535 0000231D FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4536 0000231E 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4537 00002320 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4538 00002323 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4539 00002325 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4540 00002329 EE                  <1> 	OUT	DX,AL
  4541 0000232A 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4542                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4543 0000232C 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4544 0000232E F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4545 0000232F C3                  <1> 	RETn
  4546                              <1> 
  4547                              <1> NO_MOT_WAIT:
  4548 00002330 FB                  <1> 	sti
  4549                              <1> no_mot_w1: ; 27/02/2015
  4550 00002331 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4551                              <1> 	;STI				; INTERRUPTS BACK ON
  4552 00002332 C3                  <1> 	RETn
  4553                              <1> 
  4554                              <1> ;-------------------------------------------------------------------------------
  4555                              <1> ; HD_WAIT
  4556                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4557                              <1> ;
  4558                              <1> ; ON ENTRY:	DI = DRIVE #
  4559                              <1> ;
  4560                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4561                              <1> ;-------------------------------------------------------------------------------
  4562                              <1> HD_WAIT:
  4563 00002333 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4564 00002335 E826FFFFFF          <1> 	CALL	GET_PARM
  4565 0000233A 08E4                <1> 	or	ah, ah	; 17/12/2014
  4566 0000233C 7519                <1> 	jnz	short DO_WAT
  4567 0000233E F605[1A6C0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4568                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4569                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4570                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4571 00002345 741E                <1> 	jz	short HW_DONE
  4572 00002347 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4573 00002349 8A87[296C0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4574 0000234F 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4575 00002351 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4576 00002353 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4577                              <1> ;GP3:
  4578 00002355 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4579                              <1> ;	JMP	SHORT DO_WAT
  4580                              <1> 
  4581                              <1> ;ISNT_WRITE:
  4582                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4583                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4584                              <1> 
  4585                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4586                              <1> DO_WAT:
  4587                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4588                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4589                              <1> J29:					; 	1 MILLISECOND LOOP
  4590                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4591 00002357 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4592 0000235C E874F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4593                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4594 00002361 FECC                <1> 	dec	ah
  4595 00002363 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4596                              <1> HW_DONE:
  4597 00002365 C3                  <1> 	RETn
  4598                              <1> 
  4599                              <1> ;-------------------------------------------------------------------------------
  4600                              <1> ; NEC_OUTPUT
  4601                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4602                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4603                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4604                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4605                              <1> ; 
  4606                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4607                              <1> ;
  4608                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4609                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4610                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4611                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4612                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4613                              <1> ;		AX,CX,DX DESTROYED
  4614                              <1> ;-------------------------------------------------------------------------------
  4615                              <1> 
  4616                              <1> ; 09/12/2014 [Erdogan Tan] 
  4617                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4618                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4619                              <1> ;	This read only register facilitates the transfer of data between
  4620                              <1> ;	the system microprocessor and the controller.
  4621                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4622                              <1> ;	  with the system micrprocessor.
  4623                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4624                              <1> ;	  the transfer is to the controller.
  4625                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4626                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4627                              <1> ; Bit 3 - Reserved.
  4628                              <1> ; Bit 2 - Reserved.
  4629                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4630                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4631                              <1> 
  4632                              <1> ; Data Register (3F5h)
  4633                              <1> ; This read/write register passes data, commands and parameters, and provides
  4634                              <1> ; diskette status information.
  4635                              <1>   		
  4636                              <1> NEC_OUTPUT:
  4637                              <1> 	;PUSH	BX			; SAVE REG.
  4638 00002366 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4639                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4640                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4641                              <1> 	; 16/12/2014
  4642                              <1> 	; waiting for (max.) 0.5 seconds
  4643                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4644                              <1> 	;
  4645                              <1> 	; 17/12/2014
  4646                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4647                              <1> 	;
  4648                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4649                              <1> 	;		go on.
  4650                              <1> 	;INPUT:
  4651                              <1> 	;	AH=Mask for isolation bits.
  4652                              <1> 	;	AL=pattern to look for.
  4653                              <1> 	;	DX=Port to test for
  4654                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4655                              <1> 	;	     (normally 30 microseconds per period.)
  4656                              <1> 	;
  4657                              <1> 	;WFP_SHORT:  
  4658                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4659                              <1> 	;
  4660                              <1> 
  4661                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4662                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4663 0000236A B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4664                              <1> ;
  4665                              <1> ;WFPS_OUTER_LP:
  4666                              <1> ;	;
  4667                              <1> ;WFPS_CHECK_PORT:
  4668                              <1> J23:
  4669 0000236F EC                  <1> 	IN	AL,DX			; GET STATUS
  4670 00002370 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4671 00002372 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4672 00002374 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4673                              <1> WFPS_HI:
  4674 00002376 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4675 00002378 A810                <1> 	TEST	AL,010H			; transition on memory
  4676 0000237A 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4677                              <1> WFPS_LO:
  4678 0000237C E461                <1> 	IN	AL, PORT_B		; SYS1
  4679 0000237E A810                <1> 	TEST	AL,010H
  4680 00002380 74FA                <1> 	JZ	SHORT WFPS_LO
  4681                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4682 00002382 E2EB                <1> 	loop	J23	; 27/02/2015
  4683                              <1> ;	;
  4684                              <1> ;	dec	bl
  4685                              <1> ;	jnz	short WFPS_OUTER_LP
  4686                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4687                              <1> ;J23:
  4688                              <1> ;	IN	AL,DX			; GET STATUS
  4689                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4690                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4691                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4692                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4693                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4694                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4695                              <1>    
  4696                              <1> 	;;27/02/2015
  4697                              <1> 	;16/12/2014
  4698                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4699                              <1> 	;;jb	short J23
  4700                              <1> 
  4701                              <1> ;WFPS_TIMEOUT:
  4702                              <1> 
  4703                              <1> ;-----	FALL THRU TO ERROR RETURN
  4704                              <1> 
  4705 00002384 800D[1C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4706                              <1> 	;POP	BX			; RESTORE REG.
  4707 0000238B 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4708 0000238C F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4709 0000238D C3                  <1> 	RETn
  4710                              <1> 
  4711                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4712                              <1> 
  4713                              <1> J27:	
  4714 0000238E 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4715 00002390 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4716 00002392 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4717                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4718                              <1> 	; 27/02/2015
  4719 00002393 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4720                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4721 00002394 29C9                <1> 	sub	ecx, ecx
  4722 00002396 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4723 00002398 E838F1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4724 0000239D 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4725                              <1> 	;POP	BX			; RESTORE REG
  4726 0000239E C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4727                              <1> 
  4728                              <1> ;-------------------------------------------------------------------------------
  4729                              <1> ; SEEK
  4730                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4731                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4732                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4733                              <1> ;
  4734                              <1> ; ON ENTRY:	DI = DRIVE #
  4735                              <1> ;		CH = TRACK #
  4736                              <1> ;
  4737                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4738                              <1> ;		AX,BX,CX DX DESTROYED
  4739                              <1> ;-------------------------------------------------------------------------------
  4740                              <1> SEEK:
  4741 0000239F 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4742 000023A1 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4743 000023A3 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4744 000023A5 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4745 000023A7 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4746 000023A9 8405[196C0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4747 000023AF 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4748                              <1> 
  4749 000023B1 0805[196C0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4750 000023B7 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4751 000023BC 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4752                              <1> 
  4753                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4754                              <1> 
  4755 000023BE C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4756 000023C5 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4757 000023CA 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4758                              <1> 
  4759                              <1> AFT_RECAL:
  4760 000023CC C687[2D6C0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4761 000023D3 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4762 000023D5 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4763                              <1> 
  4764                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4765                              <1> 
  4766 000023D7 F687[296C0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4767 000023DE 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4768 000023E0 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4769                              <1> 
  4770 000023E2 3AAF[2D6C0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4771 000023E8 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4772                              <1> 
  4773 000023EA BA[1D240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4774 000023EF 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4775 000023F0 88AF[2D6C0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4776 000023F6 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4777 000023F8 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4778 000023FD 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4779 000023FF 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4780 00002401 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4781 00002406 8AA7[2D6C0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4782 0000240C E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4783 00002411 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4784                              <1> 
  4785                              <1> ;-----	WAIT FOR HEAD SETTLE
  4786                              <1> 
  4787                              <1> DO_WAIT:
  4788 00002416 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4789 00002417 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4790 0000241C 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4791                              <1> RB:
  4792                              <1> NEC_ERR:
  4793                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4794                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4795 0000241D C3                  <1> 	RETn				; RETURN TO CALLER
  4796                              <1> 
  4797                              <1> ;-------------------------------------------------------------------------------
  4798                              <1> ; RECAL
  4799                              <1> ;	RECALIBRATE DRIVE
  4800                              <1> ;
  4801                              <1> ; ON ENTRY:	DI = DRIVE #
  4802                              <1> ;
  4803                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4804                              <1> ;-------------------------------------------------------------------------------
  4805                              <1> RECAL:
  4806                              <1> 	;PUSH	CX
  4807                              <1> 	; 24/12/2021
  4808 0000241E 51                  <1> 	push	ecx
  4809 0000241F B8[3B240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4810 00002424 50                  <1> 	PUSH	eAX
  4811 00002425 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4812 00002427 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4813 0000242C 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4814 0000242E 88DC                <1> 	MOV	AH,BL
  4815 00002430 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4816 00002435 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4817 0000243A 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4818                              <1> RC_BACK:
  4819                              <1> 	;POP	CX
  4820                              <1> 	; 24/12/2021
  4821 0000243B 59                  <1> 	pop	ecx
  4822 0000243C C3                  <1> 	RETn
  4823                              <1> 
  4824                              <1> ;-------------------------------------------------------------------------------
  4825                              <1> ; CHK_STAT_2
  4826                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4827                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4828                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4829                              <1> ;
  4830                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4831                              <1> ;-------------------------------------------------------------------------------
  4832                              <1> CHK_STAT_2:
  4833 0000243D B8[65240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4834 00002442 50                  <1> 	PUSH	eAX
  4835 00002443 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4836 00002448 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4837 0000244A B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4838 0000244C E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4839 00002451 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4840 00002456 720C                <1> 	JC	short J34
  4841 00002458 A0[1D6C0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4842 0000245D 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4843 0000245F 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4844 00002461 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4845 00002463 F8                  <1> 	CLC				; GOOD RETURN
  4846                              <1> J34:
  4847 00002464 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4848                              <1> CS_BACK:
  4849 00002465 C3                  <1> 	RETn
  4850                              <1> J35:
  4851 00002466 800D[1C6C0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4852 0000246D F9                  <1> 	STC				; ERROR RETURN CODE
  4853 0000246E EBF4                <1> 	JMP	SHORT J34
  4854                              <1> 
  4855                              <1> ;-------------------------------------------------------------------------------
  4856                              <1> ; WAIT_INT
  4857                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4858                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4859                              <1> ;	IF THE DRIVE IS NOT READY.
  4860                              <1> ;
  4861                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4862                              <1> ;-------------------------------------------------------------------------------
  4863                              <1> 
  4864                              <1> ; 17/12/2014
  4865                              <1> ; 2.5 seconds waiting !
  4866                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4867                              <1> ; amount of time to wait for completion interrupt from NEC.
  4868                              <1> 
  4869                              <1> 
  4870                              <1> WAIT_INT:
  4871 00002470 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4872 00002471 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4873                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4874                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4875                              <1> 
  4876                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4877                              <1> 	;
  4878                              <1> 	;WAIT_FOR_MEM:	
  4879                              <1> 	;	Waits for a bit at a specified memory location pointed
  4880                              <1> 	;	to by ES:[DI] to become set.
  4881                              <1> 	;INPUT:
  4882                              <1> 	;	AH=Mask to test with.
  4883                              <1> 	;	ES:[DI] = memory location to watch.
  4884                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4885                              <1> 	;	     (normally 30 microseconds per period.)
  4886                              <1> 
  4887                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4888                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4889                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4890                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4891                              <1> 	; 27/02/2015
  4892 00002472 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4893                              <1> WFMS_CHECK_MEM:
  4894 00002477 F605[196C0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4895 0000247E 7516                <1>         jnz     short J37
  4896                              <1> WFMS_HI:
  4897 00002480 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4898 00002482 A810                <1> 	TEST	AL,010H			; transition on memory
  4899 00002484 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4900                              <1> WFMS_LO:
  4901 00002486 E461                <1> 	IN	AL,PORT_B		;SYS1
  4902 00002488 A810                <1> 	TEST	AL,010H
  4903 0000248A 74FA                <1> 	JZ	SHORT WFMS_LO
  4904 0000248C E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4905                              <1> ;WFMS_OUTER_LP:
  4906                              <1> ;;	or	bl, bl			; check outer counter
  4907                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4908                              <1> ;	dec	bl
  4909                              <1> ;	jz	short J36A	
  4910                              <1> ;	jmp	short WFMS_CHECK_MEM
  4911                              <1> 
  4912                              <1> 	;17/12/2014
  4913                              <1> 	;16/12/2014
  4914                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4915                              <1> ;J36:
  4916                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4917                              <1> ;	JNZ	short J37
  4918                              <1> 	;16/12/2014
  4919                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4920                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4921                              <1> 	;JNZ	short J36
  4922                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4923                              <1> ;	jb	short J36
  4924                              <1> 
  4925                              <1> ;WFMS_TIMEOUT:
  4926                              <1> ;J36A:
  4927 0000248E 800D[1C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4928 00002495 F9                  <1> 	STC				; ERROR RETURN
  4929                              <1> J37:
  4930 00002496 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4931 00002497 8025[196C0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4932 0000249E 9D                  <1> 	POPF				; RECOVER CARRY
  4933 0000249F C3                  <1> 	RETn				; GOOD RETURN CODE
  4934                              <1> 
  4935                              <1> ;-------------------------------------------------------------------------------
  4936                              <1> ; RESULTS
  4937                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4938                              <1> ;	FOLLOWING AN INTERRUPT.
  4939                              <1> ;
  4940                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4941                              <1> ;		AX,BX,CX,DX DESTROYED
  4942                              <1> ;-------------------------------------------------------------------------------
  4943                              <1> RESULTS:
  4944 000024A0 57                  <1> 	PUSH	eDI
  4945 000024A1 BF[1D6C0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4946 000024A6 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4947 000024A8 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4948                              <1> 
  4949                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4950                              <1> 
  4951                              <1> _R10: 
  4952                              <1> 	; 16/12/2014
  4953                              <1> 	; wait for (max) 0.5 seconds
  4954                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4955                              <1> 	;XOR	CX,CX			; COUNTER
  4956                              <1> 
  4957                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4958                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4959                              <1> 	; 27/02/2015
  4960 000024AC B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4961                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4962                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4963                              <1> 
  4964                              <1> WFPSR_OUTER_LP:
  4965                              <1> 	;
  4966                              <1> WFPSR_CHECK_PORT:
  4967                              <1> J39:					; WAIT FOR MASTER
  4968 000024B1 EC                  <1> 	IN	AL,DX			; GET STATUS
  4969 000024B2 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4970 000024B4 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4971 000024B6 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4972                              <1> WFPSR_HI:
  4973 000024B8 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4974 000024BA A810                <1> 	TEST	AL,010H			; transition on memory
  4975 000024BC 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4976                              <1> WFPSR_LO:
  4977 000024BE E461                <1> 	IN	AL, PORT_B		; SYS1
  4978 000024C0 A810                <1> 	TEST	AL,010H
  4979 000024C2 74FA                <1> 	JZ	SHORT WFPSR_LO
  4980 000024C4 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4981                              <1> 	;; 27/02/2015
  4982                              <1> 	;;dec	bh
  4983                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4984                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4985                              <1> 
  4986                              <1> 	;;mov	byte [wait_count], 0
  4987                              <1> ;J39:					; WAIT FOR MASTER
  4988                              <1> ;	IN	AL,DX			; GET STATUS
  4989                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4990                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4991                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4992                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4993                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4994                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4995                              <1> 	;
  4996                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4997                              <1> 	;;jb	short J39	
  4998                              <1> 
  4999                              <1> ;WFPSR_TIMEOUT:
  5000 000024C6 800D[1C6C0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5001 000024CD F9                  <1> 	STC				; SET ERROR RETURN
  5002 000024CE EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5003                              <1> 
  5004                              <1> ;-----	READ IN THE STATUS
  5005                              <1> 
  5006                              <1> J42:
  5007 000024D0 EB00                <1> 	JMP	$+2			; I/O DELAY
  5008 000024D2 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5009 000024D4 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5010                              <1> 	; 16/12/2014
  5011                              <1> 	NEWIODELAY
  2107 000024D5 E6EB                <2>  out 0EBh,al
  5012 000024D7 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5013 000024D9 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5014                              <1> 	; 16/12/2014
  5015                              <1> ;	push	cx
  5016                              <1> ;	mov	cx, 30
  5017                              <1> ;wdw2:
  5018                              <1> ;	NEWIODELAY
  5019                              <1> ;	loop	wdw2
  5020                              <1> ;	pop	cx
  5021                              <1> 
  5022 000024DA B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5023 000024DF E8F1EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5024 000024E4 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5025 000024E6 EC                  <1> 	IN	AL,DX			; GET STATUS
  5026                              <1> 	; 16/12/2014
  5027                              <1> 	NEWIODELAY
  2107 000024E7 E6EB                <2>  out 0EBh,al
  5028                              <1> 	;
  5029 000024E9 A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5030 000024EB 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5031                              <1> 
  5032 000024ED FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5033 000024EF 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5034 000024F1 800D[1C6C0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5035 000024F8 F9                  <1> 	STC				; SET ERROR FLAG
  5036                              <1> 
  5037                              <1> ;-----	RESULT OPERATION IS DONE
  5038                              <1> POPRES:
  5039 000024F9 5F                  <1> 	POP	eDI
  5040 000024FA C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5041                              <1> 
  5042                              <1> ;-------------------------------------------------------------------------------
  5043                              <1> ; READ_DSKCHNG
  5044                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5045                              <1> ;
  5046                              <1> ; ON ENTRY:	DI = DRIVE #
  5047                              <1> ;
  5048                              <1> ; ON EXIT:	DI = DRIVE #
  5049                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5050                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5051                              <1> ;		AX,CX,DX DESTROYED
  5052                              <1> ;-------------------------------------------------------------------------------
  5053                              <1> READ_DSKCHNG:
  5054 000024FB E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5055 00002500 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5056 00002504 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5057 00002505 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5058 00002507 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5059                              <1> 
  5060                              <1> ;-------------------------------------------------------------------------------
  5061                              <1> ; DRIVE_DET
  5062                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5063                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5064                              <1> ; ON ENTRY:	DI = DRIVE #
  5065                              <1> ;-------------------------------------------------------------------------------
  5066                              <1> DRIVE_DET:
  5067 00002508 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5068 0000250D E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5069 00002512 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5070 00002514 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5071 00002516 E884FEFFFF          <1> 	CALL	SEEK
  5072 0000251B 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5073 0000251D B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5074                              <1> SK_GIN:
  5075 0000251F FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5076                              <1> 	;PUSH	CX			; SAVE TRACK
  5077                              <1> 	; 24/12/2021
  5078 00002521 51                  <1> 	push	ecx
  5079 00002522 E878FEFFFF          <1> 	CALL	SEEK
  5080 00002527 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5081 00002529 B8[64250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5082 0000252E 50                  <1> 	PUSH	eAX
  5083 0000252F B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5084 00002531 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5085 00002536 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5086 00002539 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5087 0000253B E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5088 00002540 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5089 00002545 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5090                              <1> 	;POP	CX			; RESTORE TRACK
  5091                              <1> 	; 24/12/2021
  5092 00002546 59                  <1> 	pop	ecx
  5093 00002547 F605[1D6C0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5094 0000254E 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5095 00002550 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5096 00002552 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5097                              <1> 
  5098                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5099                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5100                              <1> 
  5101 00002554 808F[296C0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5102 0000255B C3                  <1> 	RETn				; ALL INFORMATION SET
  5103                              <1> IS_80:
  5104 0000255C 808F[296C0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5105                              <1> DD_BAC:
  5106 00002563 C3                  <1> 	RETn
  5107                              <1> POP_BAC:
  5108                              <1> 	;POP	CX			; THROW AWAY
  5109                              <1> 	; 24/12/2021
  5110 00002564 59                  <1> 	pop	ecx
  5111 00002565 C3                  <1> 	RETn
  5112                              <1> 
  5113                              <1> fdc_int:  
  5114                              <1> 	  ; 30/07/2015	
  5115                              <1> 	  ; 16/02/2015
  5116                              <1> ;int_0Eh: ; 11/12/2014
  5117                              <1> 
  5118                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5119                              <1> ; DISK_INT
  5120                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5121                              <1> ;
  5122                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5123                              <1> ;-------------------------------------------------------------------------------
  5124                              <1> DISK_INT_1:
  5125                              <1> 
  5126                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5127                              <1> 	; 24/12/2021
  5128 00002566 50                  <1> 	push	eax
  5129 00002567 1E                  <1> 	push	ds
  5130 00002568 66B81000            <1> 	mov	ax, KDATA
  5131 0000256C 8ED8                <1> 	mov 	ds, ax
  5132 0000256E 800D[196C0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5133 00002575 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5134 00002577 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5135 00002579 1F                  <1> 	pop	ds
  5136                              <1> 	;POP	AX			; RECOVER REGISTER
  5137                              <1> 	; 24/12/2021
  5138 0000257A 58                  <1> 	pop	eax
  5139 0000257B CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5140                              <1> 
  5141                              <1> ;-------------------------------------------------------------------------------
  5142                              <1> ; DSKETTE_SETUP
  5143                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5144                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5145                              <1> ;-------------------------------------------------------------------------------
  5146                              <1> DSKETTE_SETUP:
  5147                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5148                              <1> 	;PUSH	BX
  5149                              <1> 	;PUSH	CX
  5150 0000257C 52                  <1> 	PUSH	eDX
  5151                              <1> 	;PUSH	DI
  5152                              <1> 	;;PUSH	DS
  5153                              <1> 	; 14/12/2014
  5154                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5155                              <1> 	;mov	[DISK_POINTER+2], cs
  5156                              <1> 	;
  5157                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5158 0000257D 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5159 0000257F 66C705[296C0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5159 00002587 00                  <1>
  5160 00002588 8025[246C0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5161 0000258F 800D[246C0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5162 00002596 C605[196C0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5163 0000259D C605[1B6C0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5164 000025A4 C605[1A6C0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5165 000025AB C605[1C6C0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5166                              <1> 	;
  5167                              <1> 	; 28/02/2015
  5168                              <1> 	;mov	word [cfd], 100h 
  5169 000025B2 E89DF2FFFF          <1> 	call	DSK_RESET
  5170 000025B7 5A                  <1> 	pop	edx
  5171 000025B8 C3                  <1> 	retn
  5172                              <1> 
  5173                              <1> ;SUP0:
  5174                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5175                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5176                              <1> ;	; 02/01/2015
  5177                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5178                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5179                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5180                              <1> ;       cmp     byte [fd1_type], 0	
  5181                              <1> ;	jna	short sup1
  5182                              <1> ;	or	di, di
  5183                              <1> ;	jnz	short sup1
  5184                              <1> ;	inc	di
  5185                              <1> ;       jmp     short SUP0
  5186                              <1> ;sup1:
  5187                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5188                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5189                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5190                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5191                              <1> ;	;POP	DI
  5192                              <1> ;	POP	eDX
  5193                              <1> ;	;POP	CX
  5194                              <1> ;	;POP	BX
  5195                              <1> ;	;POP	AX
  5196                              <1> ;	RETn
  5197                              <1> 
  5198                              <1> ;//////////////////////////////////////////////////////
  5199                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5200                              <1> ;
  5201                              <1> 
  5202                              <1> int13h: ; 21/02/2015
  5203 000025B9 9C                  <1> 	pushfd
  5204 000025BA 0E                  <1> 	push 	cs
  5205 000025BB E859000000          <1> 	call 	DISK_IO
  5206 000025C0 C3                  <1> 	retn
  5207                              <1> 
  5208                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5209                              <1> ;/////////////////////////////////////////////////////////////////////
  5210                              <1> 
  5211                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5212                              <1> ; 23/02/2015
  5213                              <1> ; 21/02/2015 (unix386.s)
  5214                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5215                              <1> ;
  5216                              <1> ; Original Source Code:
  5217                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5218                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5219                              <1> ;
  5220                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5221                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5222                              <1> ;
  5223                              <1> 
  5224                              <1> ;The wait for controller to be not busy is 10 seconds.
  5225                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5226                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5227                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5228                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5229                              <1> 
  5230                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5231                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5232                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5233                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5234                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5235                              <1> 
  5236                              <1> ;The wait for Data request on read and write longs is
  5237                              <1> ;2000 us. (?)
  5238                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5239                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5240                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5241                              <1> 
  5242                              <1> ; Port 61h (PORT_B)
  5243                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5244                              <1> 
  5245                              <1> ; 23/12/2014
  5246                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5247                              <1> 
  5248                              <1> ;--- INT 13H -------------------------------------------------------------------
  5249                              <1> ;									       :
  5250                              <1> ; FIXED DISK I/O INTERFACE						       :
  5251                              <1> ;									       :
  5252                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5253                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5254                              <1> ;									       :
  5255                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5256                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5257                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5258                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5259                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5260                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5261                              <1> ;									       :
  5262                              <1> ;------------------------------------------------------------------------------:
  5263                              <1> ;									       :
  5264                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5265                              <1> ;									       :
  5266                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5267                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5268                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5269                              <1> ;			  DL > 80H - DISK				       :
  5270                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5271                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5272                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5273                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5274                              <1> ;	(AH)= 06H  UNUSED						       :
  5275                              <1> ;	(AH)= 07H  UNUSED						       :
  5276                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5277                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5278                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5279                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5280                              <1> ;	(AH)= 0AH  READ LONG						       :
  5281                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5282                              <1> ;	(AH)= 0CH  SEEK 						       :
  5283                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5284                              <1> ;	(AH)= 0EH  UNUSED						       :
  5285                              <1> ;	(AH)= 0FH  UNUSED						       :
  5286                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5287                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5288                              <1> ;	(AH)= 12H  UNUSED						       :
  5289                              <1> ;	(AH)= 13H  UNUSED						       :
  5290                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5291                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5292                              <1> ;									       :
  5293                              <1> ;-------------------------------------------------------------------------------
  5294                              <1> ;									       :
  5295                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5296                              <1> ;									       :
  5297                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5298                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5299                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5300                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5301                              <1> ;									       :
  5302                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5303                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5304                              <1> ;				 (10 BITS TOTAL)			       :
  5305                              <1> ;									       :
  5306                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5307                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5308                              <1> ;									       :
  5309                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5310                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5311                              <1> ;									       :
  5312                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5313                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5314                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5315                              <1> ;			       80H FOR A BAD SECTOR			       :
  5316                              <1> ;			   N = SECTOR NUMBER				       :
  5317                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5318                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5319                              <1> ;									       :
  5320                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5321                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5322                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5323                              <1> ;									       :
  5324                              <1> ;-------------------------------------------------------------------------------
  5325                              <1> 
  5326                              <1> ;-------------------------------------------------------------------------------
  5327                              <1> ; OUTPUT								       :
  5328                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5329                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5330                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5331                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5332                              <1> ;									       :
  5333                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5334                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5335                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5336                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5337                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5338                              <1> ;		REWRITTEN.						       :
  5339                              <1> ;									       :
  5340                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5341                              <1> ;	   INPUT:							       :
  5342                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5343                              <1> ;	   OUTPUT:							       :
  5344                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5345                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5346                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5347                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5348                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5349                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5350                              <1> ;									       :
  5351                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5352                              <1> ;									       :
  5353                              <1> ;	AH = 0 - NOT PRESENT						       :
  5354                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5355                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5356                              <1> ;	     3 - FIXED DISK						       :
  5357                              <1> ;									       :
  5358                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5359                              <1> ;									       :
  5360                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5361                              <1> ;	INFORMATION.							       :
  5362                              <1> ;									       :
  5363                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5364                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5365                              <1> ;									       :
  5366                              <1> ;-------------------------------------------------------------------------------
  5367                              <1> 
  5368                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5369                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5370                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5371                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5372                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5373                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5374                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5375                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5376                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5377                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5378                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5379                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5380                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5381                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5382                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5383                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5384                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5385                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5386                              <1> 
  5387                              <1> ;--------------------------------------------------------
  5388                              <1> ;							:
  5389                              <1> ; FIXED DISK PARAMETER TABLE				:
  5390                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5391                              <1> ;							:
  5392                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5393                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5394                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5395                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5396                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5397                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5398                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5399                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5400                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5401                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5402                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5403                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5404                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5405                              <1> ;							:
  5406                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5407                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5408                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5409                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5410                              <1> ;							:
  5411                              <1> ;--------------------------------------------------------
  5412                              <1> 
  5413                              <1> ;--------------------------------------------------------
  5414                              <1> ;							:
  5415                              <1> ; HARDWARE SPECIFIC VALUES				:
  5416                              <1> ;							:
  5417                              <1> ;  -  CONTROLLER I/O PORT				:
  5418                              <1> ;							:
  5419                              <1> ;     > WHEN READ FROM: 				:
  5420                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5421                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5422                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5423                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5424                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5425                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5426                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5427                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5428                              <1> ;							:
  5429                              <1> ;     > WHEN WRITTEN TO:				:
  5430                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5431                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5432                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5433                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5434                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5435                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5436                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5437                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5438                              <1> ;							:
  5439                              <1> ;--------------------------------------------------------
  5440                              <1> 
  5441                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5442                              <1> ;HF1_PORT	equ	0170h	
  5443                              <1> ;HF_REG_PORT	EQU	03F6H
  5444                              <1> ;HF1_REG_PORT	equ	0376h
  5445                              <1> 
  5446                              <1> HDC1_BASEPORT	equ	1F0h
  5447                              <1> HDC2_BASEPORT	equ	170h		
  5448                              <1> 
  5449 000025C1 90                  <1> align 2
  5450                              <1> 
  5451                              <1> ;-----		STATUS REGISTER
  5452                              <1> 
  5453                              <1> ST_ERROR	EQU	00000001B	;
  5454                              <1> ST_INDEX	EQU	00000010B	;
  5455                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5456                              <1> ST_DRQ		EQU	00001000B	;
  5457                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5458                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5459                              <1> ST_READY	EQU	01000000B	;
  5460                              <1> ST_BUSY 	EQU	10000000B	;
  5461                              <1> 
  5462                              <1> ;-----		ERROR REGISTER
  5463                              <1> 
  5464                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5465                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5466                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5467                              <1> ;		EQU	00001000B	; NOT USED
  5468                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5469                              <1> ;		EQU	00100000B	; NOT USED
  5470                              <1> ERR_DATA_ECC	EQU	01000000B
  5471                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5472                              <1> 
  5473                              <1> 
  5474                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5475                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5476                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5477                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5478                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5479                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5480                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5481                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5482                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5483                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5484                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5485                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5486                              <1> 
  5487                              <1> ;MAX_FILE	EQU	2
  5488                              <1> ;S_MAX_FILE	EQU	2
  5489                              <1> MAX_FILE	equ	4		; 22/12/2014
  5490                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5491                              <1> 
  5492                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5493                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5494                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5495                              <1> 
  5496                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5497                              <1> 
  5498                              <1> ;-----		COMMAND BLOCK REFERENCE
  5499                              <1> 
  5500                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5501                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5502                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5503                              <1> ; 19/12/2014
  5504                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5505                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5506                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5507                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5508                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5509                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5510                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5511                              <1> 
  5512                              <1> align 2
  5513                              <1> 
  5514                              <1> ;----------------------------------------------------------------
  5515                              <1> ; FIXED DISK I/O SETUP						:
  5516                              <1> ;								:
  5517                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5518                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5519                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5520                              <1> ;								:
  5521                              <1> ;----------------------------------------------------------------
  5522                              <1> 
  5523                              <1> DISK_SETUP:
  5524                              <1> 	;CLI
  5525                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5526                              <1> 	;xor	ax,ax
  5527                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5528                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5529                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5530                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5531                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5532                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5533                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5534                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5535                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5536                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5537                              <1> 	;;MOV	[HDISK_INT+2],CS
  5538                              <1> 	;mov	[HDISK_INT1+2],CS
  5539                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5540                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5541                              <1> 	;mov	[HDISK_INT2+2],CS
  5542                              <1> 	;
  5543                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5544                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5545                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5546                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5547                              <1> 	;push	cs
  5548                              <1> 	;pop	ds
  5549                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5550                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5551 000025C2 C705[346C0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5551 000025CA 0900                <1>
  5552                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5553                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5554 000025CC C705[386C0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5554 000025D4 0900                <1>
  5555                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5556                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5557 000025D6 C705[3C6C0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5557 000025DE 0900                <1>
  5558                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5559                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5560 000025E0 C705[406C0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5560 000025E8 0900                <1>
  5561                              <1> 	;
  5562                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5563                              <1> 	;;;AND	AL,0BFH
  5564                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5565                              <1> 	;;;JMP	$+2
  5566                              <1> 	;;IODELAY
  5567                              <1> 	;;OUT	INTB01,AL
  5568                              <1> 	;;IODELAY
  5569                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5570                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5571                              <1> 	;;;JMP	$+2
  5572                              <1> 	;;IODELAY
  5573                              <1> 	;;OUT	INTA01,AL
  5574                              <1> 	;
  5575                              <1> 	;STI
  5576                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5577                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5578                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5579                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5580                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5581                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5582                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5583                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5584                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5585                              <1> 	;mov	si, hd0_type
  5586 000025EA BE[90660000]        <1> 	mov	esi, hd0_type
  5587                              <1> 	;mov	cx, 4
  5588 000025EF B904000000          <1> 	mov	ecx, 4
  5589                              <1> hde_l:
  5590 000025F4 AC                  <1> 	lodsb
  5591 000025F5 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5592 000025F7 7206                <1> 	jb	short _L4
  5593 000025F9 FE05[306C0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5594                              <1> _L4: ; 26/02/2015
  5595 000025FF E2F3                <1> 	loop	hde_l	
  5596                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5597                              <1> ;L4:
  5598                              <1> 	; 
  5599                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5600                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5601                              <1> 	;;mov 	cl, 3
  5602                              <1> 	;;
  5603                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5604                              <1> ;;hdc_dl:
  5605                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5606                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5607                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5608                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5609                              <1> 	;;jnc	short hdc_reset0
  5610                              <1> 	;;loop	hdc_dl
  5611                              <1> 	;;; 27/12/2014
  5612                              <1> 	;;stc
  5613                              <1> 	;;retn
  5614                              <1> 	;
  5615                              <1> ;;hdc_reset0:
  5616                              <1> 	; 18/01/2015
  5617 00002601 8A0D[306C0000]      <1> 	mov	cl, [HF_NUM]
  5618 00002607 20C9                <1> 	and	cl, cl
  5619 00002609 740D                <1> 	jz	short POD_DONE
  5620                              <1> 	;
  5621 0000260B B27F                <1> 	mov	dl, 7Fh
  5622                              <1> hdc_reset1:
  5623 0000260D FEC2                <1> 	inc	dl
  5624                              <1> 	;; 31/12/2015
  5625                              <1> 	;;push	dx
  5626                              <1> 	;;push	cx
  5627                              <1> 	;;push	ds
  5628                              <1> 	;;sub	ax, ax
  5629                              <1> 	;;mov	ds, ax
  5630                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5631                              <1> 	;;pop	ds
  5632                              <1> 	;;MOV	BX,AX
  5633                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5634                              <1> 	;;MOV	CX,AX
  5635                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5636                              <1> 	;;
  5637                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5638                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5639                              <1> 	;;pop	cx
  5640                              <1> 	;;pop	dx
  5641                              <1> 	;;
  5642                              <1> 	; 18/01/2015
  5643 0000260F B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5644                              <1> 	;int	13h
  5645 00002611 E8A3FFFFFF          <1> 	call	int13h
  5646 00002616 E2F5                <1> 	loop	hdc_reset1
  5647                              <1> POD_DONE:
  5648 00002618 C3                  <1> 	RETn
  5649                              <1> 
  5650                              <1> ;;-----	POD_ERROR
  5651                              <1> 
  5652                              <1> ;;CTL_ERRX:
  5653                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5654                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5655                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5656                              <1> ;	;JMP	short POD_DONE
  5657                              <1> 
  5658                              <1> ;;HD_RESET_1:
  5659                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5660                              <1> ;;	;PUSH	CX
  5661                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5662                              <1> ;;	INT	13H
  5663                              <1> ;;	JC	short RES_2
  5664                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5665                              <1> ;;	INT	13H
  5666                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5667                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5668                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5669                              <1> ;;					; (30 seconds)		
  5670                              <1> ;;	;cmc
  5671                              <1> ;;	;JNC	short RES_1
  5672                              <1> ;;	jb	short RES_1
  5673                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5674                              <1> ;;	;TEST	DL,1
  5675                              <1> ;;	;JNZ	RES_E1
  5676                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5677                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5678                              <1> ;;	;JMP	SHORT RES_E1
  5679                              <1> ;;RES_ER: ; 22/12/2014
  5680                              <1> ;;RES_OK:
  5681                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5682                              <1> ;;	;POP	BX
  5683                              <1> ;;	RETn
  5684                              <1> ;;
  5685                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5686                              <1> ;;	INT	13H
  5687                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5688                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5689                              <1> ;;	INT	13H
  5690                              <1> ;;	JC	short RES_ER
  5691                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5692                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5693                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5694                              <1> ;;	INT	13H
  5695                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5696                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5697                              <1> ;;	JE	short RES_OK
  5698                              <1> ;;	CMP	AH,DATA_CORRECTED
  5699                              <1> ;;	JE	short RES_OK
  5700                              <1> ;;	CMP	AH,BAD_ECC
  5701                              <1> ;;	JE	short RES_OK
  5702                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5703                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5704                              <1> ;;					; (60 seconds)		
  5705                              <1> ;;	cmc
  5706                              <1> ;;	JC	short RES_ER		; FAILED
  5707                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5708                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5709                              <1> ;;	AND	AL,3FH
  5710                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5711                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5712                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5713                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5714                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5715                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5716                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5717                              <1> ;;	;TEST	DL,1
  5718                              <1> ;;	;JNZ	short RES_E1
  5719                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5720                              <1> ;;;RES_E1:
  5721                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5722                              <1> ;;;RES_OK:
  5723                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5724                              <1> ;;	;POP	BX
  5725                              <1> ;;	;RETn
  5726                              <1> ;
  5727                              <1> ;;SET_FAIL:
  5728                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5729                              <1> ;	;CALL	CMOS_READ
  5730                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5731                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5732                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5733                              <1> ;	;RETn
  5734                              <1> ;
  5735                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5736                              <1> ;	;POP	AX			; SAVE RETURN
  5737                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5738                              <1> ;	;POP	BX
  5739                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5740                              <1> ;	;PUSH	CX
  5741                              <1> ;	;PUSH	AX
  5742                              <1> ;	;push	ds
  5743                              <1> ;	;xor	ax, ax
  5744                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5745                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5746                              <1> ;	;				; BX = START TIME
  5747                              <1> ;	;				; CX = END TIME
  5748                              <1> ;	;pop	ds
  5749                              <1> ;	;CMP	BX,CX
  5750                              <1> ;	;JB	short TCHK1		; START < END
  5751                              <1> ;	;CMP	BX,AX
  5752                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5753                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5754                              <1> ;;TCHK1: CMP	AX,BX
  5755                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5756                              <1> ;;TCHK2: CMP	AX,CX
  5757                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5758                              <1> ;;					; OR CURRENT < END < START
  5759                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5760                              <1> ;;	RETn
  5761                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5762                              <1> ;;	RETn
  5763                              <1> ;;
  5764                              <1> ;;int_13h:
  5765                              <1> 
  5766                              <1> ;----------------------------------------
  5767                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5768                              <1> ;----------------------------------------
  5769                              <1> 
  5770                              <1> DISK_IO:
  5771 00002619 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5772                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5773                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5774                              <1> 	;;call	int40h
  5775                              <1> 	;jb	DISKETTE_IO_1
  5776                              <1> 	; 24/12/2021
  5777 0000261C 7305                <1> 	jnb	short A1
  5778 0000261E E95FF1FFFF          <1> 	jmp	DISKETTE_IO_1
  5779                              <1> ;RET_2:
  5780                              <1> 	;RETf	2			; BACK TO CALLER
  5781                              <1> ;	retf	4
  5782                              <1> A1:
  5783 00002623 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5784                              <1> 	;; 04/01/2015
  5785                              <1> 	;;OR	AH,AH
  5786                              <1> 	;;JNZ	short A2
  5787                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5788                              <1> 	;;SUB	AH,AH
  5789 00002624 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5790 00002627 772E                <1> 	JA	short RET_2
  5791                              <1> 	; 18/01/2015
  5792 00002629 08E4                <1> 	or	ah,ah
  5793 0000262B 742D                <1> 	jz	short A4
  5794 0000262D 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5795 00002630 7504                <1> 	jne	short A2
  5796 00002632 28E4                <1> 	sub	ah,ah	; Reset
  5797 00002634 EB24                <1> 	jmp	short A4
  5798                              <1> A2:
  5799 00002636 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5800                              <1> 	;JNZ	short A3
  5801                              <1>         ;JMP    GET_PARM_N
  5802                              <1> 	;je	GET_PARM_N
  5803                              <1> 	; 24/12/2021
  5804 00002639 7505                <1> 	jne	short A3
  5805 0000263B E90D030000          <1> 	jmp	GET_PARM_N
  5806                              <1> A3:	
  5807 00002640 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5808                              <1> 	;JNZ	short A4
  5809                              <1>         ;JMP    READ_DASD_TYPE
  5810                              <1> 	;je	READ_DASD_TYPE
  5811                              <1> 	; 24/12/2021
  5812 00002643 7505                <1> 	jne	short A3_A4
  5813 00002645 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5814                              <1> A3_A4:
  5815                              <1> 	; 02/02/2015
  5816 0000264A 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5817                              <1> 	; 12/01/2015
  5818 0000264D F5                  <1> 	cmc
  5819 0000264E 730A                <1> 	jnc	short A4
  5820                              <1> 	; 30/01/2015
  5821                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5822 00002650 C605[2F6C0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5823                              <1> 	;jmp	short RET_2
  5824                              <1> RET_2:
  5825 00002657 CA0400              <1> 	retf	4
  5826                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5827 0000265A C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5828 0000265E 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5829 0000265F 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5830 00002660 52                  <1> 	PUSH	eDX
  5831 00002661 1E                  <1> 	PUSH	DS
  5832 00002662 06                  <1> 	PUSH	ES
  5833 00002663 56                  <1> 	PUSH	eSI
  5834 00002664 57                  <1> 	PUSH	eDI
  5835                              <1> 	;;04/01/2015
  5836                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5837                              <1> 	;;JNZ	short A5
  5838                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5839                              <1> ;;A5:	
  5840                              <1> 	;push	cs
  5841                              <1> 	;pop	ds
  5842                              <1> 	; 21/02/2015
  5843                              <1> 	;push	ax
  5844                              <1> 	; 24/12/2021
  5845 00002665 50                  <1> 	push	eax
  5846 00002666 66B81000            <1> 	mov	ax, KDATA
  5847 0000266A 8ED8                <1> 	mov	ds, ax
  5848 0000266C 8EC0                <1> 	mov	es, ax	
  5849                              <1> 	;pop	ax
  5850                              <1> 	; 24/12/2021
  5851 0000266E 58                  <1> 	pop	eax
  5852 0000266F E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5853                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5854 00002674 8A25[2F6C0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5855 0000267A 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5856 0000267D F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5857 0000267E 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5858 0000267F 5E                  <1> 	POP	eSI
  5859 00002680 07                  <1>         POP     ES
  5860 00002681 1F                  <1>         POP     DS
  5861 00002682 5A                  <1> 	POP	eDX
  5862 00002683 59                  <1> 	POP	eCX
  5863 00002684 5B                  <1> 	POP	eBX
  5864 00002685 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5865                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5866 00002686 CA0400              <1> 	retf	4
  5867                              <1> ; 21/02/2015
  5868                              <1> ;       dw --> dd
  5869                              <1> M1:					; FUNCTION TRANSFER TABLE
  5870 00002689 [42280000]          <1> 	dd	DISK_RESET		; 000H
  5871 0000268D [B7280000]          <1> 	dd	RETURN_STATUS		; 001H
  5872 00002691 [C4280000]          <1> 	dd	DISK_READ		; 002H
  5873 00002695 [CD280000]          <1> 	dd	DISK_WRITE		; 003H
  5874 00002699 [D6280000]          <1> 	dd	DISK_VERF		; 004H
  5875 0000269D [EE280000]          <1> 	dd	FMT_TRK 		; 005H
  5876 000026A1 [38280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5877 000026A5 [38280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5878 000026A9 [38280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5879 000026AD [AF290000]          <1> 	dd	INIT_DRV		; 009H
  5880 000026B1 [0E2A0000]          <1> 	dd	RD_LONG 		; 00AH
  5881 000026B5 [172A0000]          <1> 	dd	WR_LONG 		; 00BH
  5882 000026B9 [202A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5883 000026BD [42280000]          <1> 	dd	DISK_RESET		; 00DH
  5884 000026C1 [38280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5885 000026C5 [38280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5886 000026C9 [482A0000]          <1> 	dd	TST_RDY 		; 010H
  5887 000026CD [6C2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5888 000026D1 [38280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5889 000026D5 [38280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5890 000026D9 [A22A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5891                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5892 000026DD [38280000]          <1> 	dd	BAD_COMMAND		; 015h
  5893 000026E1 [38280000]          <1> 	dd	BAD_COMMAND		; 016h
  5894 000026E5 [38280000]          <1> 	dd	BAD_COMMAND		; 017h
  5895 000026E9 [38280000]          <1> 	dd	BAD_COMMAND		; 018h
  5896 000026ED [38280000]          <1> 	dd	BAD_COMMAND		; 019h
  5897 000026F1 [38280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5898 000026F5 [C4280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5899 000026F9 [CD280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5900                              <1> M1L     EQU    $-M1
  5901                              <1> 
  5902                              <1> DISK_IO_CONT:
  5903                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5904 000026FD 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5905                              <1> 	;;JNZ	short SU0
  5906                              <1>         ;;JMP	RETURN_STATUS
  5907                              <1> 	;je	RETURN_STATUS
  5908                              <1> 	; 24/12/2021
  5909 00002700 7505                <1> 	jne	short SU0
  5910 00002702 E9B0010000          <1> 	jmp	RETURN_STATUS
  5911                              <1> SU0:
  5912 00002707 C605[2F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5913                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5914                              <1> 	;mov	si, bx ;; 14/02/2015
  5915 0000270E 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5916 00002710 8A1D[306C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5917                              <1> 	;; 04/01/2015
  5918                              <1> 	;;PUSH	AX
  5919 00002716 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5920                              <1> 					; (get drive number as 0 to 3)
  5921 00002719 38D3                <1> 	CMP	BL,DL
  5922                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5923                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5924                              <1> 	; 24/12/2021
  5925 0000271B 7705                <1> 	ja	short su0_su1
  5926 0000271D E916010000          <1> 	jmp	BAD_COMMAND
  5927                              <1> su0_su1:
  5928                              <1>         ;;03/01/2015
  5929 00002722 29DB                <1> 	sub	ebx, ebx
  5930 00002724 88D3                <1> 	mov	bl, dl
  5931                              <1> 	;sub	bh, bh
  5932 00002726 883D[446C0000]      <1> 	mov	[LBAMode], bh 	; 0
  5933                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5934                              <1> 	;test	byte [ebx+hd0_type], 1
  5935                              <1> 	;jz	short su1		; no
  5936                              <1> 	;inc	byte [LBAMode]
  5937                              <1> ;su1:
  5938                              <1> 	; 21/02/2015 (32 bit modification)
  5939                              <1> 	; 04/01/2015
  5940                              <1> 	;push	ax ; ***
  5941                              <1> 	; 24/12/2021
  5942 0000272C 50                  <1> 	push	eax ; ***
  5943                              <1> 	;PUSH	ES ; **
  5944                              <1> 	;PUSH	DX ; *
  5945                              <1> 	; 24/12/2021
  5946 0000272D 52                  <1> 	push	edx ; *
  5947                              <1> 	;push	ax
  5948 0000272E 50                  <1> 	push	eax
  5949 0000272F E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5950                              <1> 	; 02/02/2015
  5951                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5952 00002734 668B4310            <1> 	mov	ax, [ebx+16]
  5953 00002738 66A3[84660000]      <1> 	mov	[HF_PORT], ax
  5954                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5955 0000273E 668B5312            <1> 	mov	dx, [ebx+18]
  5956 00002742 668915[86660000]    <1> 	mov	[HF_REG_PORT], dx
  5957                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5958 00002749 8A4314              <1> 	mov	al, [ebx+20]
  5959                              <1> 	; 23/02/2015
  5960 0000274C A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5961 0000274E 7406                <1> 	jz 	short su1
  5962 00002750 FE05[446C0000]      <1> 	inc	byte [LBAMode] ; 1 
  5963                              <1> su1: 	 
  5964 00002756 C0E804              <1> 	shr 	al, 4
  5965 00002759 2401                <1> 	and	al, 1			
  5966 0000275B A2[88660000]        <1> 	mov	[hf_m_s], al 
  5967                              <1> 	;
  5968                              <1> 	; 03/01/2015
  5969                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5970 00002760 8A4308              <1> 	mov	al, [ebx+8]
  5971                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5972 00002763 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5973                              <1> 					; Control Byte:  (= 08h, here)
  5974                              <1> 					; bit 0 - 0
  5975                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5976                              <1> 					; bit 2 - SRST (software RESET)
  5977                              <1> 					; bit 3 - use extra heads (8 to 15)
  5978                              <1> 					;         -always set to 1-	
  5979                              <1> 					; (bits 3 to 7 are reserved
  5980                              <1> 					;          for ATA devices)
  5981 00002764 8A25[316C0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5982 0000276A 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5983 0000276D 08C4                <1> 	OR	AH,AL
  5984 0000276F 8825[316C0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5985                              <1> 	; 04/01/2015
  5986                              <1> 	;pop	ax
  5987                              <1> 	; 24/12/2021
  5988 00002775 58                  <1> 	pop	eax
  5989                              <1> 	;pop	dx ; * ;; 14/02/2015
  5990                              <1> 	; 24/12/2021
  5991 00002776 5A                  <1> 	pop	edx ; *
  5992 00002777 20E4                <1> 	and	ah, ah	; Reset function ?
  5993 00002779 7506                <1> 	jnz	short su2
  5994                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5995                              <1> 	;pop	es ; **
  5996                              <1> 	;pop	ax ; ***
  5997                              <1> 	; 24/12/2021
  5998 0000277B 58                  <1> 	pop	eax ; ***	
  5999                              <1> 	;;pop	bx
  6000 0000277C E9C1000000          <1>         jmp     DISK_RESET
  6001                              <1> su2:
  6002 00002781 803D[446C0000]00    <1> 	cmp	byte [LBAMode], 0
  6003 00002788 765E                <1> 	jna	short su3
  6004                              <1> 	;
  6005                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6006 0000278A 80FC1B              <1> 	cmp	ah, 1Bh
  6007 0000278D 720B                <1> 	jb	short lbarw1
  6008 0000278F 80FC1C              <1> 	cmp	ah, 1Ch
  6009 00002792 7759                <1> 	ja 	short invldfnc
  6010                              <1> 	;;pop	dx ; * ; 14/02/2015
  6011                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6012 00002794 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6013                              <1> 	;; 14/02/2015
  6014 00002796 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6015                              <1> 	;;mov	dx, bx
  6016                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6017                              <1> 	;;mov	bx, di
  6018                              <1> 	;mov	si, di ; Buffer offset
  6019 00002798 EB2E                <1> 	jmp	short lbarw2
  6020                              <1> lbarw1:
  6021                              <1> 	; convert CHS to LBA
  6022                              <1> 	;
  6023                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6024                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6025                              <1> 	;	+ Sector - 1
  6026                              <1> 	;push	dx ; * ;; 14/02/2015
  6027                              <1> 	; 24/12/2021
  6028 0000279A 52                  <1> 	push	edx ; *
  6029                              <1> 	;xor	dh, dh
  6030 0000279B 31D2                <1> 	xor	edx, edx
  6031                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6032 0000279D 8A530E              <1> 	mov	dl, [ebx+14]
  6033                              <1> 	;xor	ah, ah
  6034 000027A0 31C0                <1> 	xor	eax, eax
  6035                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6036 000027A2 8A4302              <1> 	mov	al, [ebx+2]
  6037 000027A5 FEC8                <1> 	dec	al
  6038                              <1> 	;inc	ax		; 0 =  256
  6039 000027A7 40                  <1> 	inc	eax ; 24/12/2021
  6040 000027A8 66F7E2              <1> 	mul 	dx
  6041                              <1> 		; AX = # of Heads" * Sectors/Track
  6042 000027AB 6689CA              <1> 	mov	dx, cx
  6043                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6044 000027AE 83E13F              <1> 	and	ecx, 3fh
  6045 000027B1 86D6                <1> 	xchg	dl, dh
  6046 000027B3 C0EE06              <1> 	shr	dh, 6
  6047                              <1> 		; DX = cylinder (0 to 1023)
  6048                              <1> 	;mul 	dx
  6049                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6050 000027B6 F7E2                <1> 	mul	edx
  6051 000027B8 FEC9                <1> 	dec	cl  ; sector - 1
  6052                              <1> 	;add	ax, cx
  6053                              <1> 	;adc	dx, 0
  6054                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6055 000027BA 01C8                <1> 	add	eax, ecx
  6056                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6057                              <1> 	; 24/12/2021
  6058 000027BC 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6059                              <1> 	;push	dx
  6060                              <1> 	;push	ax
  6061 000027BD 50                  <1> 	push	eax
  6062                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6063 000027BE 8A430E              <1> 	mov	al, [ebx+14]
  6064 000027C1 F6E5                <1> 	mul	ch
  6065                              <1> 		; AX = Head * Sectors/Track
  6066 000027C3 6699                <1>         cwd
  6067                              <1> 	;pop	dx
  6068 000027C5 5A                  <1> 	pop	edx
  6069                              <1> 	;add	ax, dx
  6070                              <1> 	;pop	dx
  6071                              <1> 	;adc	dx, 0 ; add carry bit
  6072 000027C6 01D0                <1> 	add	eax, edx
  6073                              <1> lbarw2:
  6074 000027C8 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6075 000027CA 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6076 000027CC C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6077                              <1> 				; NOTE: Features register (1F1h, 171h)
  6078                              <1> 				; is not used for ATA device R/W functions. 
  6079                              <1> 				; It is old/obsolete 'write precompensation'
  6080                              <1> 				; register and error register
  6081                              <1> 				; for old ATA/IDE devices.
  6082                              <1> 	; 18/01/2014
  6083                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6084 000027D0 8A0D[88660000]      <1> 	mov	cl, [hf_m_s]
  6085                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6086                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6087                              <1> 				; bit 6 = 1 = LBA mode
  6088                              <1> 				; bit 7 = 1
  6089 000027D6 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6090                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6091 000027D9 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6092 000027DE C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6093                              <1> 	;or	dh, ch
  6094 000027E1 09C8                <1> 	or	eax, ecx	
  6095                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6096                              <1> 				  ; (Sector Number Register)
  6097                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6098                              <1> 				  ; (Cylinder Low Register)
  6099                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6100                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6101                              <1> 				  ; (Cylinder High Register)
  6102                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6103                              <1> 				  ; (Drive/Head Register)
  6104                              <1> 	
  6105                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6106 000027E3 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6107                              <1> 	;14/02/2015
  6108                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6109 000027E6 EB37                <1> 	jmp	short su4
  6110                              <1> su3:
  6111                              <1> 	; 02/02/2015 
  6112                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6113 000027E8 80FC14              <1> 	cmp 	ah, 14h
  6114 000027EB 7603                <1> 	jna 	short chsfnc
  6115                              <1> invldfnc:
  6116                              <1>         ; 14/02/2015  
  6117                              <1> 	;pop	es ; **
  6118                              <1>         ;pop	ax ; ***
  6119                              <1>         ; 24/12/2021
  6120 000027ED 58                  <1> 	pop	eax ; ***
  6121                              <1> 	;jmp	short BAD_COMMAND_POP
  6122 000027EE EB48                <1>         jmp     short BAD_COMMAND
  6123                              <1> chsfnc:	
  6124                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6125 000027F0 668B4305            <1> 	mov	ax, [ebx+5]
  6126 000027F4 66C1E802            <1> 	SHR	AX,2
  6127 000027F8 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6128                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6129                              <1> 	;;PUSH	DX
  6130                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6131                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6132                              <1> 	;;POP	DX ; * 
  6133                              <1> 	;;POP	ES ; **
  6134                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6135                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6136                              <1> 	;;OR	AH,AL
  6137                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6138                              <1> 	;
  6139 000027FB 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6140 000027FD 243F                <1> 	AND	AL,3FH
  6141 000027FF 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6142 00002802 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6143 00002805 88C8                <1> 	MOV	AL,CL
  6144 00002807 C0E806              <1> 	SHR	AL,6
  6145 0000280A 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6146                              <1> 	;;05/01/2015
  6147                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6148 0000280D A0[88660000]        <1> 	mov	al, [hf_m_s]
  6149 00002812 C0E004              <1> 	SHL	AL,4
  6150 00002815 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6151 00002818 08F0                <1> 	OR	AL,DH
  6152                              <1> 	;OR	AL,80H or 20H
  6153 0000281A 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6154 0000281C 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6155                              <1> su4:
  6156                              <1> 	;POP	ES ; **
  6157                              <1>         ;; 14/02/2015
  6158                              <1>         ;;POP   AX
  6159                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6160                              <1>         ;;PUSH  AX
  6161                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6162                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6163                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6164                              <1> 	;pop     ax ; ***
  6165                              <1> 	; 24/12/2021
  6166 0000281F 58                  <1> 	pop	eax ; ***
  6167 00002820 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6168 00002823 29DB                <1>         sub	ebx, ebx
  6169 00002825 88E3                <1> 	mov     bl, ah
  6170                              <1>         ;xor	bh, bh
  6171                              <1>         ;sal	bx, 1
  6172 00002827 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6173                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6174                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6175                              <1>         ;;JNB   short BAD_COMMAND_POP
  6176                              <1>         ;cmp	bx, M1L
  6177 0000282B 83FB74              <1> 	cmp	ebx, M1L
  6178 0000282E 7308                <1> 	jnb	short BAD_COMMAND
  6179                              <1>         ;xchg	bx, si
  6180 00002830 87DE                <1>         xchg	ebx, esi
  6181                              <1> 	;;;POP	AX			; RESTORE AX
  6182                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6183                              <1> 	
  6184                              <1> 	;;PUSH	CX
  6185                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6186                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6187                              <1> 	;SHR	CX,4
  6188                              <1> 	;MOV	AX,ES
  6189                              <1> 	;ADD	AX,CX
  6190                              <1> 	;MOV	ES,AX
  6191                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6192                              <1> 	;;POP	AX
  6193                              <1> 	;;POP	CX
  6194                              <1> 	;;JMP	word [CS:SI+M1]
  6195                              <1> 	;jmp	word [SI+M1]
  6196 00002832 FFA6[89260000]      <1> 	jmp	dword [esi+M1]
  6197                              <1> ;;BAD_COMMAND_POP:
  6198                              <1> ;;	POP	AX
  6199                              <1> ;;	POP	BX
  6200                              <1> BAD_COMMAND:
  6201 00002838 C605[2F6C0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6202 0000283F B000                <1> 	MOV	AL,0
  6203 00002841 C3                  <1> 	RETn
  6204                              <1> 
  6205                              <1> ;----------------------------------------
  6206                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6207                              <1> ;----------------------------------------
  6208                              <1> 
  6209                              <1> ; 18-1-2015 : one controller reset (not other one)
  6210                              <1> 
  6211                              <1> DISK_RESET:
  6212 00002842 FA                  <1> 	CLI
  6213 00002843 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6214                              <1> 	;JMP	$+2
  6215                              <1> 	IODELAY
  2102 00002845 EB00                <2>  jmp short $+2
  2103 00002847 EB00                <2>  jmp short $+2
  6216                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6217 00002849 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6218 0000284B E6A1                <1> 	OUT	INTB01,AL
  6219 0000284D FB                  <1> 	STI				; START INTERRUPTS
  6220                              <1> 	; 14/02/2015
  6221                              <1> 	;mov	di, dx
  6222                              <1> 	; 24/12/2021
  6223 0000284E 89D7                <1> 	mov	edi, edx	
  6224                              <1> 	; 04/01/2015
  6225                              <1> 	;xor	di,di
  6226                              <1> drst0:
  6227 00002850 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6228                              <1> 	;MOV	DX,HF_REG_PORT
  6229 00002852 668B15[86660000]    <1> 	MOV	DX,[HF_REG_PORT]
  6230 00002859 EE                  <1> 	OUT	DX,AL			; RESET
  6231                              <1> ;	MOV	CX,10			; DELAY COUNT
  6232                              <1> ;DRD:	DEC	CX
  6233                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6234                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6235 0000285A B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6236 0000285F E871ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6237                              <1>                                         ; 40 micro seconds)
  6238 00002864 A0[316C0000]        <1> 	mov	al,[CONTROL_BYTE]
  6239 00002869 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6240 0000286B EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6241 0000286C E807040000          <1> 	CALL	NOT_BUSY
  6242 00002871 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6243 00002873 668B15[84660000]    <1> 	MOV	DX,[HF_PORT]
  6244 0000287A FEC2                <1> 	inc	dl  ; HF_PORT+1
  6245                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6246                              <1>         ;mov	cl, 10
  6247 0000287C B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6248                              <1> drst1:
  6249 00002881 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6250 00002882 3C01                <1> 	CMP	AL,1
  6251                              <1> 	; 04/01/2015
  6252 00002884 740A                <1> 	jz	short drst2
  6253                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6254                              <1>         	; Drive/Head Register - bit 4
  6255 00002886 E2F9                <1> 	loop	drst1
  6256                              <1> DRERR:	
  6257 00002888 C605[2F6C0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6258 0000288F C3                  <1> 	RETn
  6259                              <1> drst2:
  6260                              <1> 	; 14/02/2015
  6261                              <1> 	;mov	dx, di
  6262                              <1> 	; 24/12/2021
  6263 00002890 89FA                <1> 	mov	edx, edi
  6264                              <1> ;drst3:
  6265                              <1> ;	; 05/01/2015
  6266                              <1> ;	shl 	di,1
  6267                              <1> ;	; 04/01/2015
  6268                              <1> ;	mov	ax,[di+hd_cports]
  6269                              <1> ;	cmp	ax,[HF_REG_PORT]
  6270                              <1> ;	je	short drst4
  6271                              <1> ;	mov	[HF_REG_PORT], ax
  6272                              <1> ;	; 03/01/2015
  6273                              <1> ;	mov	ax,[di+hd_ports]
  6274                              <1> ;       mov     [HF_PORT], ax
  6275                              <1> ;	; 05/01/2014
  6276                              <1> ;	shr	di,1
  6277                              <1> ;	; 04/01/2015
  6278                              <1> ;	jmp	short drst0	; reset other controller
  6279                              <1> ;drst4:
  6280                              <1> ;	; 05/01/2015
  6281                              <1> ;	shr	di,1
  6282                              <1> ;	mov	al,[di+hd_dregs]
  6283                              <1> ;	and	al,10h ; bit 4 only
  6284                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6285                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6286                              <1> 	;
  6287 00002892 A0[88660000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6288 00002897 A801                <1> 	test	al,1
  6289                              <1> ;	jnz	short drst6
  6290 00002899 7516                <1>         jnz     short drst4
  6291 0000289B 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6292                              <1> ;drst5:
  6293                              <1> drst3:
  6294 0000289F E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6295                              <1> 	;mov	dx,di
  6296 000028A4 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6297                              <1> 	; 04/01/2014
  6298                              <1> ;	inc	di
  6299                              <1> ;	mov	dx,di
  6300                              <1> ;	cmp	dl,[HF_NUM]
  6301                              <1> ;	jb	short drst3
  6302                              <1> ;DRE:
  6303 000028A9 C605[2F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6304 000028B0 C3                  <1> 	RETn
  6305                              <1> ;drst6:
  6306                              <1> drst4:		; Drive/Head Register - bit 4
  6307 000028B1 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6308                              <1>         ;jmp    short drst5
  6309 000028B5 EBE8                <1>         jmp     short drst3
  6310                              <1> 
  6311                              <1> ;----------------------------------------
  6312                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6313                              <1> ;----------------------------------------
  6314                              <1> 
  6315                              <1> RETURN_STATUS:
  6316 000028B7 A0[2F6C0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6317 000028BC C605[2F6C0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6318 000028C3 C3                  <1> 	RETn
  6319                              <1> 
  6320                              <1> ;----------------------------------------
  6321                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6322                              <1> ;----------------------------------------
  6323                              <1> 
  6324                              <1> DISK_READ:
  6325 000028C4 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6326 000028C8 E92A020000          <1>         JMP     COMMANDI
  6327                              <1> 
  6328                              <1> ;----------------------------------------
  6329                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6330                              <1> ;----------------------------------------
  6331                              <1> 
  6332                              <1> DISK_WRITE:
  6333 000028CD C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6334 000028D1 E976020000          <1>         JMP     COMMANDO
  6335                              <1> 
  6336                              <1> ;----------------------------------------
  6337                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6338                              <1> ;----------------------------------------
  6339                              <1> 
  6340                              <1> DISK_VERF:
  6341 000028D6 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6342 000028DA E8E4020000          <1> 	CALL	COMMAND
  6343 000028DF 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6344 000028E1 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6345 000028E6 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6346 000028E8 E8E3030000          <1> 	CALL	CHECK_STATUS
  6347                              <1> VERF_EXIT:
  6348 000028ED C3                  <1> 	RETn
  6349                              <1> 
  6350                              <1> ;----------------------------------------
  6351                              <1> ;	FORMATTING	     (AH = 05H) :
  6352                              <1> ;----------------------------------------
  6353                              <1> 
  6354                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6355 000028EE C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6356                              <1> 	;PUSH	ES
  6357                              <1> 	;PUSH	BX
  6358 000028F2 53                  <1> 	push	ebx
  6359 000028F3 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6360                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6361 000028F8 8A430E              <1> 	mov	al, [ebx+14]
  6362 000028FB 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6363 000028FE 5B                  <1> 	pop	ebx
  6364                              <1> 	;POP	BX
  6365                              <1> 	;POP	ES
  6366 000028FF E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6367                              <1> 
  6368                              <1> ;----------------------------------------
  6369                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6370                              <1> ;----------------------------------------
  6371                              <1> 
  6372                              <1> READ_DASD_TYPE:
  6373                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6374 00002904 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6375                              <1> 	;PUSH	ES
  6376 00002905 53                  <1> 	PUSH	eBX
  6377                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6378                              <1> 	;push	cs
  6379                              <1> 	;pop	ds
  6380 00002906 66BB1000            <1>         mov	bx, KDATA
  6381 0000290A 8EDB                <1> 	mov	ds, bx
  6382                              <1> 	;mov	es, bx
  6383 0000290C C605[2F6C0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6384 00002913 8A1D[306C0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6385 00002919 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6386 0000291C 38D3                <1> 	CMP	BL,DL
  6387 0000291E 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6388 00002920 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6389                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6390 00002925 8A4302              <1> 	mov	al, [ebx+2]
  6391                              <1> 	;MOV	CL,[ES:BX+14]
  6392 00002928 8A4B0E              <1> 	mov	cl, [ebx+14]
  6393 0000292B F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6394                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6395 0000292D 668B0B              <1> 	mov	cx, [ebx]
  6396                              <1> 	;
  6397                              <1> 	; 02/01/2015 
  6398                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6399                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6400 00002930 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6401                              <1> 	;
  6402 00002932 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6403 00002935 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6404 00002938 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6405                              <1> 	;SUB	AX,AX
  6406 0000293B 28C0                <1> 	sub	al, al
  6407 0000293D B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6408 0000293F 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6409                              <1> 	;POP	ES
  6410 00002940 1F                  <1> 	POP	DS
  6411 00002941 F8                  <1> 	CLC				; CLEAR CARRY
  6412                              <1> 	;RETf	2
  6413 00002942 CA0400              <1> 	retf	4
  6414                              <1> RDT_NOT_PRESENT:
  6415                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6416                              <1> 	; 24/12/2021
  6417 00002945 29C0                <1> 	sub	eax, eax
  6418                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6419                              <1> 	;MOV	DX,AX
  6420 00002947 89C1                <1> 	mov	ecx, eax
  6421 00002949 89C2                <1> 	mov	edx, eax
  6422 0000294B EBF2                <1> 	JMP	short RDT2
  6423                              <1> 
  6424                              <1> ;----------------------------------------
  6425                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6426                              <1> ;----------------------------------------
  6427                              <1> 
  6428                              <1> GET_PARM_N:
  6429                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6430 0000294D 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6431                              <1> 	;PUSH	ES
  6432 0000294E 53                  <1> 	PUSH	eBX
  6433                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6434                              <1> 	;MOV	DS,AX
  6435                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6436                              <1> 	;JZ	short G0
  6437                              <1> 	;LES	BX,@HF1_TBL_VEC
  6438                              <1> 	;JMP	SHORT G1
  6439                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6440                              <1> ;G1:
  6441                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6442                              <1> 	; 22/12/2014
  6443                              <1> 	;push	cs
  6444                              <1> 	;pop	ds
  6445 0000294F 66BB1000            <1> 	mov	bx, KDATA
  6446 00002953 8EDB                <1> 	mov	ds, bx
  6447                              <1> 	;mov	es, bx
  6448                              <1> 	;
  6449 00002955 80EA80              <1> 	SUB	DL,80H
  6450 00002958 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6451 0000295B 7340                <1> 	JAE	short G4
  6452                              <1> 	;
  6453 0000295D 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6454                              <1> 	; 22/12/2014
  6455 0000295F 88D3                <1> 	mov	bl, dl
  6456                              <1> 	;xor	bh, bh  
  6457 00002961 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6458                              <1> 	;add	bx, HF_TBL_VEC
  6459 00002964 81C3[346C0000]      <1> 	add	ebx, HF_TBL_VEC
  6460                              <1> 	;mov	ax, [bx+2]
  6461                              <1> 	;mov	es, ax			; dpt segment
  6462                              <1> 	;mov	bx, [bx]		; dpt offset
  6463 0000296A 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6464                              <1> 
  6465 0000296C C605[2F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6466                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6467 00002973 668B03              <1> 	mov	ax, [ebx]
  6468                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6469 00002976 6648                <1> 	dec	ax			; max. cylinder number
  6470 00002978 88C5                <1> 	MOV	CH,AL
  6471 0000297A 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6472 0000297E 66D1E8              <1> 	SHR	AX,1
  6473 00002981 66D1E8              <1> 	SHR	AX,1
  6474                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6475 00002984 0A430E              <1> 	or	al, [ebx+14]
  6476 00002987 88C1                <1> 	MOV	CL,AL
  6477                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6478 00002989 8A7302              <1> 	mov	dh, [ebx+2]
  6479 0000298C FECE                <1> 	DEC	DH			; 0-N RANGE
  6480 0000298E 8A15[306C0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6481                              <1> 	;SUB	AX,AX
  6482                              <1> 	; 24/12/2021
  6483 00002994 29C0                <1> 	sub	eax, eax
  6484                              <1> 	; 27/12/2014 
  6485                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6486                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6487                              <1> 	;mov	di, bx			; HDPT offset
  6488 00002996 89DF                <1> 	mov	edi, ebx
  6489                              <1> G5:
  6490 00002998 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6491                              <1> 	;POP	ES
  6492 00002999 1F                  <1> 	POP	DS
  6493                              <1> 	;RETf	2
  6494 0000299A CA0400              <1> 	retf	4
  6495                              <1> G4:
  6496 0000299D C605[2F6C0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6497                              <1> 	; 24/12/2021
  6498 000029A4 29C0                <1> 	sub	eax, eax
  6499 000029A6 B407                <1> 	MOV	AH,INIT_FAIL
  6500                              <1> 	;SUB	AL,AL
  6501                              <1> 	;SUB	DX,DX
  6502 000029A8 29D2                <1> 	sub	edx, edx
  6503                              <1> 	;SUB	CX,CX
  6504 000029AA 29C9                <1> 	sub	ecx, ecx
  6505 000029AC F9                  <1> 	STC				; SET ERROR FLAG
  6506 000029AD EBE9                <1> 	JMP	short G5
  6507                              <1> 
  6508                              <1> ;----------------------------------------
  6509                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6510                              <1> ;----------------------------------------
  6511                              <1> 	; 03/01/2015
  6512                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6513                              <1> 	; logical sector per logical track
  6514                              <1> 	; and logical heads - 1 would be set but
  6515                              <1> 	; it is seen as it will be good
  6516                              <1> 	; if physical parameters will be set here
  6517                              <1> 	; because, number of heads <= 16.
  6518                              <1> 	; (logical heads usually more than 16)
  6519                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6520                              <1> 	;	== INT 13h physical parameters
  6521                              <1> 
  6522                              <1> ;INIT_DRV:
  6523                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6524                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6525                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6526                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6527                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6528                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6529                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6530                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6531                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6532                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6533                              <1> ;	SUB	AX,AX
  6534                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6535                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6536                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6537                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6538                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6539                              <1> ;	CALL	CHECK_STATUS
  6540                              <1> ;INIT_EXIT:
  6541                              <1> ;	RETn
  6542                              <1> 
  6543                              <1> ; 04/01/2015
  6544                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6545                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6546                              <1> INIT_DRV:
  6547                              <1> 	;xor	ah,ah
  6548 000029AF 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6549 000029B1 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6550 000029B3 3825[446C0000]      <1>         cmp     [LBAMode], ah   ; 0
  6551 000029B9 7702                <1> 	ja	short idrv0
  6552 000029BB B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6553                              <1> idrv0:
  6554                              <1> 	; DL = drive number (0 based)
  6555 000029BD E8BB030000          <1> 	call	GET_VEC
  6556                              <1> 	;push	bx
  6557 000029C2 53                  <1> 	push	ebx ; 21/02/2015
  6558                              <1> 	;add	bx,ax
  6559 000029C3 01C3                <1> 	add	ebx,eax
  6560                              <1> 	;; 05/01/2015
  6561 000029C5 8A25[88660000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6562                              <1> 	;;and 	ah,1 
  6563 000029CB C0E404              <1> 	shl	ah,4
  6564 000029CE 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6565                              <1> 	;mov	al,[es:bx]
  6566 000029D1 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6567 000029D3 FEC8                <1> 	dec	al	 ; last head number 
  6568                              <1> 	;and	al,0Fh
  6569 000029D5 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6570                              <1> 	;
  6571 000029D7 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6572 000029DB 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6573                              <1> 	;pop	bx
  6574 000029DE 5B                  <1> 	pop	ebx
  6575 000029DF 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6576 000029E1 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6577 000029E3 803D[446C0000]00    <1> 	cmp	byte [LBAMode],0
  6578 000029EA 7702                <1> 	ja	short idrv1
  6579 000029EC B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6580                              <1> idrv1:
  6581                              <1> 	;xor	ah,ah
  6582                              <1> 	;add	bx,ax
  6583 000029EE 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6584                              <1> 	;mov	al,[es:bx]
  6585                              <1> 			; sector number
  6586 000029F0 8A03                <1> 	mov	al,[ebx]
  6587 000029F2 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6588 000029F5 28C0                <1> 	sub	al,al
  6589 000029F7 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6590 000029FA E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6591 000029FF 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6592 00002A01 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6593 00002A06 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6594 00002A08 E8C3020000          <1> 	call	CHECK_STATUS
  6595                              <1> INIT_EXIT:
  6596 00002A0D C3                  <1> 	RETn
  6597                              <1> 
  6598                              <1> ;----------------------------------------
  6599                              <1> ;	READ LONG	     (AH = 0AH) :
  6600                              <1> ;----------------------------------------
  6601                              <1> 
  6602                              <1> RD_LONG:
  6603                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6604 00002A0E C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6605 00002A12 E9E0000000          <1>         JMP     COMMANDI
  6606                              <1> 
  6607                              <1> ;----------------------------------------
  6608                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6609                              <1> ;----------------------------------------
  6610                              <1> 
  6611                              <1> WR_LONG:
  6612                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6613 00002A17 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6614 00002A1B E92C010000          <1>         JMP     COMMANDO
  6615                              <1> 
  6616                              <1> ;----------------------------------------
  6617                              <1> ;	SEEK		     (AH = 0CH) :
  6618                              <1> ;----------------------------------------
  6619                              <1> 
  6620                              <1> DISK_SEEK:
  6621 00002A20 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6622 00002A24 E89A010000          <1> 	CALL	COMMAND
  6623 00002A29 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6624 00002A2B E80C020000          <1> 	CALL	_WAIT
  6625 00002A30 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6626 00002A32 E899020000          <1> 	CALL	CHECK_STATUS
  6627 00002A37 803D[2F6C0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6628 00002A3E 7507                <1> 	JNE	short DS_EXIT
  6629 00002A40 C605[2F6C0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6630                              <1> DS_EXIT:
  6631 00002A47 C3                  <1> 	RETn
  6632                              <1> 
  6633                              <1> ;----------------------------------------
  6634                              <1> ;	TEST DISK READY      (AH = 10H) :
  6635                              <1> ;----------------------------------------
  6636                              <1> 
  6637                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6638 00002A48 E82B020000          <1> 	CALL	NOT_BUSY
  6639 00002A4D 751C                <1> 	JNZ	short TR_EX
  6640 00002A4F 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6641 00002A52 668B15[84660000]    <1> 	MOV	DX,[HF_PORT]
  6642 00002A59 80C206              <1> 	add	dl,6
  6643 00002A5C EE                  <1> 	OUT	DX,AL
  6644 00002A5D E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6645 00002A62 7507                <1> 	JNZ	short TR_EX
  6646 00002A64 C605[2F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6647                              <1> TR_EX:	
  6648 00002A6B C3                  <1> 	RETn
  6649                              <1> 
  6650                              <1> ;----------------------------------------
  6651                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6652                              <1> ;----------------------------------------
  6653                              <1> 
  6654                              <1> HDISK_RECAL:
  6655 00002A6C C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6656 00002A70 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6657 00002A75 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6658 00002A77 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6659 00002A7C 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6660 00002A7E E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6661 00002A83 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6662                              <1> RECAL_X:
  6663 00002A85 E846020000          <1> 	CALL	CHECK_STATUS
  6664 00002A8A 803D[2F6C0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6665 00002A91 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6666 00002A93 C605[2F6C0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6667                              <1> RECAL_EXIT:
  6668 00002A9A 803D[2F6C0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6669 00002AA1 C3                  <1> 	RETn
  6670                              <1> 
  6671                              <1> ;----------------------------------------
  6672                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6673                              <1> ;----------------------------------------
  6674                              <1> 
  6675                              <1> CTLR_DIAGNOSTIC:
  6676 00002AA2 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6677 00002AA3 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6678                              <1> 	;AND	AL,0BFH
  6679 00002AA5 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6680                              <1> 	;JMP	$+2
  6681                              <1> 	IODELAY
  2102 00002AA7 EB00                <2>  jmp short $+2
  2103 00002AA9 EB00                <2>  jmp short $+2
  6682 00002AAB E6A1                <1> 	OUT	INTB01,AL
  6683                              <1> 	IODELAY
  2102 00002AAD EB00                <2>  jmp short $+2
  2103 00002AAF EB00                <2>  jmp short $+2
  6684 00002AB1 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6685 00002AB3 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6686                              <1> 	;JMP	$+2
  6687                              <1> 	IODELAY
  2102 00002AB5 EB00                <2>  jmp short $+2
  2103 00002AB7 EB00                <2>  jmp short $+2
  6688 00002AB9 E621                <1> 	OUT	INTA01,AL
  6689 00002ABB FB                  <1> 	STI
  6690 00002ABC E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6691 00002AC1 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6692                              <1> 	;MOV	DX, HF_PORT+7
  6693 00002AC3 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6694 00002ACA 80C207              <1> 	add	dl, 7
  6695 00002ACD B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6696 00002ACF EE                  <1> 	OUT	DX,AL
  6697 00002AD0 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6698 00002AD5 B480                <1> 	MOV	AH,TIME_OUT
  6699 00002AD7 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6700                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6701 00002AD9 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6702 00002AE0 FEC2                <1> 	inc	dl
  6703 00002AE2 EC                  <1> 	IN	AL,DX
  6704 00002AE3 A2[266C0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6705 00002AE8 B400                <1> 	MOV	AH,0
  6706 00002AEA 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6707 00002AEC 7402                <1> 	JE	SHORT CD_EXIT
  6708 00002AEE B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6709                              <1> CD_EXIT:
  6710 00002AF0 8825[2F6C0000]      <1> 	MOV	[DISK_STATUS1],AH
  6711 00002AF6 C3                  <1> 	RETn
  6712                              <1> 
  6713                              <1> ;----------------------------------------
  6714                              <1> ; COMMANDI				:
  6715                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6716                              <1> ;	NSECTOR RETURNS ZERO		:
  6717                              <1> ;----------------------------------------
  6718                              <1> COMMANDI:
  6719 00002AF7 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6720 00002AFC 724D                <1> 	JC	short CMD_ABORT
  6721                              <1> 	;MOV	DI,BX
  6722 00002AFE 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6723 00002B00 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6724 00002B05 7544                <1> 	JNZ	short CMD_ABORT
  6725                              <1> CMD_I1:
  6726 00002B07 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6727 00002B0C 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6728                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6729 00002B0E B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6730                              <1> 	;MOV	DX,HF_PORT
  6731 00002B13 668B15[84660000]    <1> 	mov	dx,[HF_PORT]
  6732 00002B1A FA                  <1> 	CLI
  6733 00002B1B FC                  <1> 	CLD
  6734 00002B1C F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6735 00002B1F FB                  <1> 	STI
  6736 00002B20 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6737 00002B24 7419                <1> 	JZ	CMD_I3
  6738 00002B26 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6739 00002B2B 721E                <1> 	JC	short TM_OUT
  6740                              <1> 	;MOV	DX,HF_PORT
  6741 00002B2D 668B15[84660000]    <1> 	mov	dx,[HF_PORT]
  6742                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6743 00002B34 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6744 00002B39 EC                  <1> CMD_I2: IN	AL,DX
  6745                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6746 00002B3A 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6747 00002B3C 47                  <1> 	INC	eDI
  6748 00002B3D E2FA                <1> 	LOOP	CMD_I2
  6749 00002B3F E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6750 00002B44 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6751 00002B46 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6752 00002B49 75BC                <1> 	JNZ	SHORT CMD_I1
  6753                              <1> CMD_ABORT:
  6754 00002B4B C3                  <1> TM_OUT: RETn
  6755                              <1> 
  6756                              <1> ;----------------------------------------
  6757                              <1> ; COMMANDO				:
  6758                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6759                              <1> ;	NSECTOR RETURNS ZERO		:
  6760                              <1> ;----------------------------------------
  6761                              <1> COMMANDO:
  6762 00002B4C E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6763 00002B51 72F8                <1> 	JC	short CMD_ABORT
  6764 00002B53 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6765 00002B55 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6766 00002B5A 75EF                <1> 	JNZ	short CMD_ABORT
  6767 00002B5C E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6768 00002B61 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6769                              <1> CMD_O1: ;PUSH	DS
  6770                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6771                              <1> 	;POP	DS
  6772                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6773                              <1> 	;MOV	DX,HF_PORT
  6774                              <1> 	; 01/02/2015
  6775 00002B63 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6776                              <1> 	;push	es
  6777                              <1> 	;pop	ds
  6778                              <1> 	;mov	cx, 256
  6779 00002B6A B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6780 00002B6F FA                  <1> 	CLI
  6781 00002B70 FC                  <1> 	CLD
  6782 00002B71 F3666F              <1> 	REP	OUTSW
  6783 00002B74 FB                  <1> 	STI
  6784                              <1> 	;POP	DS			; RESTORE DS
  6785 00002B75 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6786 00002B79 7419                <1> 	JZ	short CMD_O3
  6787 00002B7B E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6788 00002B80 72C9                <1> 	JC	short TM_OUT
  6789                              <1> 	;MOV	DX,HF_PORT
  6790 00002B82 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6791                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6792 00002B89 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6793                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6794 00002B8E 8A06                <1> 	mov	al, [esi]
  6795 00002B90 EE                  <1> 	OUT	DX,AL
  6796 00002B91 46                  <1> 	INC	eSI
  6797 00002B92 E2FA                <1> 	LOOP	CMD_O2
  6798                              <1> CMD_O3:
  6799 00002B94 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6800 00002B99 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6801 00002B9B E830010000          <1> 	CALL	CHECK_STATUS
  6802 00002BA0 75A9                <1> 	JNZ	short CMD_ABORT
  6803 00002BA2 F605[256C0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6804 00002BA9 75B8                <1> 	JNZ	SHORT CMD_O1
  6805                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6806 00002BAB 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6807                              <1> 	;add	dl, 2
  6808 00002BB2 FEC2                <1> 	inc	dl
  6809 00002BB4 FEC2                <1> 	inc	dl
  6810 00002BB6 EC                  <1> 	IN	AL,DX			;
  6811 00002BB7 A8FF                <1> 	TEST	AL,0FFH 		;
  6812 00002BB9 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6813 00002BBB C605[2F6C0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6814                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6815                              <1> CMD_O4:
  6816 00002BC2 C3                  <1> 	RETn
  6817                              <1> 
  6818                              <1> ;--------------------------------------------------------
  6819                              <1> ; COMMAND						:
  6820                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6821                              <1> ; OUTPUT						:
  6822                              <1> ;	BL = STATUS					:
  6823                              <1> ;	BH = ERROR REGISTER				:
  6824                              <1> ;--------------------------------------------------------
  6825                              <1> 
  6826                              <1> COMMAND:
  6827 00002BC3 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6828                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6829                              <1> COMMAND1:
  6830                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6831 00002BC4 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6832                              <1> 	;;POP	CX
  6833 00002BC9 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6834 00002BCB 803D[2F6C0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6835                              <1> 	;JZ	short CMD_TIMEOUT
  6836                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6837                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6838 00002BD2 7507                <1> 	jne	short COMMAND4
  6839                              <1> CMD_TIMEOUT:
  6840 00002BD4 C605[2F6C0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6841                              <1> COMMAND4:
  6842 00002BDB 5B                  <1> 	POP	eBX
  6843 00002BDC 803D[2F6C0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6844 00002BE3 C3                  <1> 	RETn
  6845                              <1> COMMAND2:
  6846 00002BE4 5B                  <1> 	POP	eBX
  6847 00002BE5 57                  <1> 	PUSH	eDI
  6848 00002BE6 C605[276C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6849 00002BED FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6850 00002BEE E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6851                              <1> 	;AND	AL,0BFH
  6852 00002BF0 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6853                              <1> 	;JMP	$+2
  6854                              <1> 	IODELAY
  2102 00002BF2 EB00                <2>  jmp short $+2
  2103 00002BF4 EB00                <2>  jmp short $+2
  6855 00002BF6 E6A1                <1> 	OUT	INTB01,AL
  6856 00002BF8 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6857 00002BFA 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6858                              <1> 	;JMP	$+2
  6859                              <1> 	IODELAY
  2102 00002BFC EB00                <2>  jmp short $+2
  2103 00002BFE EB00                <2>  jmp short $+2
  6860 00002C00 E621                <1> 	OUT	INTA01,AL
  6861 00002C02 FB                  <1> 	STI
  6862 00002C03 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6863                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6864 00002C05 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  6865 00002C0C FEC2                <1> 	inc	dl
  6866 00002C0E F605[316C0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6867 00002C15 7411                <1> 	JZ	short COMMAND3
  6868 00002C17 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6869 00002C1A 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6870 00002C1C 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6871 00002C1E 7208                <1> 	JB	short COMMAND3
  6872 00002C20 3C40                <1> 	CMP	AL,40H
  6873 00002C22 7704                <1> 	JA	short COMMAND3
  6874 00002C24 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6875                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6876                              <1> COMMAND3:
  6877 00002C28 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6878 00002C2C EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6879                              <1> 	IODELAY
  2102 00002C2D EB00                <2>  jmp short $+2
  2103 00002C2F EB00                <2>  jmp short $+2
  6880 00002C31 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6881 00002C32 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6882 00002C34 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6883 00002C38 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6884 00002C3A 5F                  <1> 	POP	eDI
  6885 00002C3B C3                  <1> 	RETn				; ZERO FLAG IS SET
  6886                              <1> 
  6887                              <1> ;CMD_TIMEOUT:
  6888                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6889                              <1> ;COMMAND4:
  6890                              <1> ;	POP	BX
  6891                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6892                              <1> ;	RETn
  6893                              <1> 
  6894                              <1> ;----------------------------------------
  6895                              <1> ;	WAIT FOR INTERRUPT		:
  6896                              <1> ;----------------------------------------
  6897                              <1> ;WAIT:
  6898                              <1> _WAIT:
  6899 00002C3C FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6900                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6901                              <1> 	;CLC
  6902                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6903                              <1> 	;INT	15H
  6904                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6905                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6906                              <1> 
  6907                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6908                              <1> 	;; 21/02/2015
  6909                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6910                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6911 00002C3D B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6912                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6913                              <1> ;-----	WAIT LOOP
  6914                              <1> 
  6915                              <1> WT1:	
  6916                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6917 00002C42 F605[276C0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6918                              <1> 	;LOOPZ	WT1
  6919 00002C49 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6920                              <1> 	;DEC	BL
  6921                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6922                              <1> 
  6923                              <1> WT1_hi:
  6924 00002C4B E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6925 00002C4D A810                <1> 	test	al, 10h			; transition on memory
  6926 00002C4F 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6927                              <1> WT1_lo:
  6928 00002C51 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6929 00002C53 A810                <1> 	test	al, 10h			
  6930 00002C55 74FA                <1> 	jz	short WT1_lo
  6931 00002C57 E2E9                <1> 	loop	WT1
  6932                              <1> 	;;or	bl, bl
  6933                              <1> 	;;jz	short WT2	
  6934                              <1> 	;;dec	bl
  6935                              <1> 	;;jmp	short WT1
  6936                              <1> 	;dec	bl
  6937                              <1> 	;jnz	short WT1	
  6938                              <1> 
  6939 00002C59 C605[2F6C0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6940 00002C60 EB0E                <1> 	JMP	SHORT WT4
  6941 00002C62 C605[2F6C0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6942 00002C69 C605[276C0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6943 00002C70 803D[2F6C0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6944 00002C77 C3                  <1> 	RETn
  6945                              <1> 
  6946                              <1> ;----------------------------------------
  6947                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6948                              <1> ;----------------------------------------
  6949                              <1> NOT_BUSY:
  6950 00002C78 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6951                              <1> 	;PUSH	eBX
  6952                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6953 00002C79 668B15[84660000]    <1> 	mov	DX, [HF_PORT]
  6954 00002C80 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6955                              <1> 	;MOV	BL,DELAY_1
  6956                              <1> 					; wait for 10 seconds
  6957                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6958                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6959                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6960 00002C83 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6961                              <1> 	;
  6962                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6963                              <1> NB1:	
  6964 00002C88 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6965                              <1> 	;TEST	AL,ST_BUSY
  6966 00002C89 2480                <1> 	and	al, ST_BUSY
  6967                              <1> 	;LOOPNZ	NB1
  6968 00002C8B 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6969                              <1> 	;DEC	BL			
  6970                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6971                              <1> 
  6972 00002C8D E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6973 00002C8F A810                <1> 	TEST	AL,010H			; transition on memory
  6974 00002C91 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6975 00002C93 E461                <1> NB1_lo: IN	AL,SYS1
  6976 00002C95 A810                <1> 	TEST	AL,010H
  6977 00002C97 74FA                <1> 	JZ	short NB1_lo
  6978 00002C99 E2ED                <1> 	LOOP	NB1
  6979                              <1> 	;dec	bl
  6980                              <1> 	;jnz	short NB1
  6981                              <1> 	;
  6982                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6983                              <1> ;;	jb	short NB1
  6984                              <1> 	;
  6985                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6986                              <1> 	;JMP	SHORT NB3
  6987 00002C9B B080                <1> 	mov	al, TIME_OUT
  6988                              <1> NB2:	
  6989                              <1> 	;MOV	byte [DISK_STATUS1],0
  6990                              <1> ;NB3:	
  6991                              <1> 	;POP	eBX
  6992 00002C9D A2[2F6C0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6993                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6994 00002CA2 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6995 00002CA4 C3                  <1> 	RETn
  6996                              <1> 
  6997                              <1> ;----------------------------------------
  6998                              <1> ;	WAIT FOR DATA REQUEST		:
  6999                              <1> ;----------------------------------------
  7000                              <1> WAIT_DRQ:
  7001                              <1> 	;MOV	CX,DELAY_3
  7002                              <1> 	;MOV	DX,HF_PORT+7
  7003 00002CA5 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  7004 00002CAC 80C207              <1> 	add	dl, 7
  7005                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7006                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7007                              <1> 					; (but it is written as 2000
  7008                              <1> 					; micro seconds in ATORGS.ASM file
  7009                              <1> 					; of Award Bios - 1999, D1A0622)
  7010 00002CAF B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7011 00002CB4 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7012 00002CB5 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7013 00002CB7 7516                <1> 	JNZ	short WQ_OK
  7014                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7015                              <1> WQ_hi:	
  7016 00002CB9 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7017 00002CBB A810                <1> 	TEST	AL,010H			; transition on memory
  7018 00002CBD 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7019 00002CBF E461                <1> WQ_lo:  IN      AL,SYS1
  7020 00002CC1 A810                <1> 	TEST	AL,010H
  7021 00002CC3 74FA                <1> 	JZ	SHORT WQ_lo
  7022 00002CC5 E2ED                <1> 	LOOP	WQ_1
  7023                              <1> 
  7024 00002CC7 C605[2F6C0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7025 00002CCE F9                  <1> 	STC
  7026                              <1> WQ_OK:
  7027 00002CCF C3                  <1> 	RETn
  7028                              <1> ;WQ_OK:	;CLC
  7029                              <1> ;	RETn
  7030                              <1> 
  7031                              <1> ;----------------------------------------
  7032                              <1> ;	CHECK FIXED DISK STATUS 	:
  7033                              <1> ;----------------------------------------
  7034                              <1> CHECK_STATUS:
  7035 00002CD0 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7036 00002CD5 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7037 00002CD7 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7038 00002CD9 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7039 00002CDB E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7040                              <1> CHECK_S1:
  7041 00002CE0 803D[2F6C0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7042 00002CE7 C3                  <1> 	RETn
  7043                              <1> 
  7044                              <1> ;----------------------------------------
  7045                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7046                              <1> ;----------------------------------------
  7047                              <1> CHECK_ST:
  7048                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7049 00002CE8 668B15[84660000]    <1> 	mov	dx, [HF_PORT]
  7050 00002CEF 80C207              <1> 	add	dl, 7
  7051 00002CF2 EC                  <1> 	IN	AL,DX
  7052 00002CF3 A2[256C0000]        <1> 	MOV	[HF_STATUS],AL
  7053 00002CF8 B400                <1> 	MOV	AH,0
  7054 00002CFA A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7055 00002CFC 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7056 00002CFE B4CC                <1> 	MOV	AH,WRITE_FAULT
  7057 00002D00 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7058 00002D02 7514                <1> 	JNZ	short CKST_EXIT
  7059 00002D04 B4AA                <1> 	MOV	AH,NOT_RDY
  7060 00002D06 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7061 00002D08 740E                <1> 	JZ	short CKST_EXIT
  7062 00002D0A B440                <1> 	MOV	AH,BAD_SEEK
  7063 00002D0C A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7064 00002D0E 7408                <1> 	JZ	short CKST_EXIT
  7065 00002D10 B411                <1> 	MOV	AH,DATA_CORRECTED
  7066 00002D12 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7067 00002D14 7502                <1> 	JNZ	short CKST_EXIT
  7068 00002D16 B400                <1> 	MOV	AH,0
  7069                              <1> CKST_EXIT:
  7070 00002D18 8825[2F6C0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7071 00002D1E 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7072 00002D21 7403                <1> 	JZ	short CKST_EX1
  7073 00002D23 80FC00              <1> 	CMP	AH,0
  7074                              <1> CKST_EX1:
  7075 00002D26 C3                  <1> 	RETn
  7076                              <1> 
  7077                              <1> ;----------------------------------------
  7078                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7079                              <1> ;----------------------------------------
  7080                              <1> CHECK_ER:
  7081                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7082 00002D27 668B15[84660000]    <1> 	mov	dx, [HF_PORT]		;
  7083 00002D2E FEC2                <1> 	inc	dl
  7084 00002D30 EC                  <1> 	IN	AL,DX
  7085 00002D31 A2[266C0000]        <1> 	MOV	[HF_ERROR],AL
  7086 00002D36 53                  <1> 	PUSH	eBX ; 21/02/2015
  7087 00002D37 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7088 00002D3C D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7089 00002D3E 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7090 00002D40 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7091 00002D42 BB[78660000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7092 00002D47 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7093                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7094                              <1> 	;mov	ah, [bx]
  7095 00002D49 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7096 00002D4B 8825[2F6C0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7097 00002D51 5B                  <1> 	POP	eBX
  7098 00002D52 80FC00              <1> 	CMP	AH,0
  7099 00002D55 C3                  <1> 	RETn
  7100                              <1> 
  7101                              <1> ;--------------------------------------------------------
  7102                              <1> ; CHECK_DMA						:
  7103                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7104                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7105                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7106                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7107                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7108                              <1> ;  -ERROR OTHERWISE					:
  7109                              <1> ;--------------------------------------------------------
  7110                              <1> CHECK_DMA:
  7111                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7112                              <1> 	; 24/12/2021
  7113 00002D56 50                  <1> 	push	eax
  7114 00002D57 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7115 00002D5B F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7116 00002D5F 7404                <1> 	JZ	short CKD1
  7117 00002D61 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7118 00002D65 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7119 00002D68 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7120 00002D6A 7207                <1> 	JB	short CKDERR		; TOO MANY
  7121 00002D6C 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7122 00002D6E 7203                <1> 	JB	short CKDERR		; ERROR
  7123 00002D70 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7124                              <1> 	;POP	AX
  7125                              <1> 	; 24/12/2021
  7126 00002D71 58                  <1> 	pop	eax
  7127 00002D72 C3                  <1> 	RETn				; NORMAL RETURN
  7128 00002D73 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7129 00002D74 C605[2F6C0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7130                              <1> 	;POP	AX
  7131                              <1> 	; 24/12/2021
  7132 00002D7B 58                  <1> 	pop	eax	
  7133 00002D7C C3                  <1> 	RETn
  7134                              <1> 
  7135                              <1> ;----------------------------------------
  7136                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7137                              <1> ;----------------------------------------
  7138                              <1> 					
  7139                              <1> ; INPUT -> DL = 0 based drive number
  7140                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7141                              <1> 
  7142                              <1> GET_VEC:
  7143                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7144                              <1> 	;MOV	ES,AX
  7145                              <1> 	;TEST	DL,1
  7146                              <1> 	;JZ	short GV_0
  7147                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7148                              <1> ;	JMP	SHORT GV_EXIT
  7149                              <1> ;GV_0:
  7150                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7151                              <1> ;
  7152                              <1> 	;xor	bh, bh
  7153 00002D7D 31DB                <1> 	xor	ebx, ebx
  7154 00002D7F 88D3                <1> 	mov	bl, dl
  7155                              <1> 	;;02/01/2015
  7156                              <1> 	;;shl	bl, 1			; port address offset
  7157                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7158                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7159 00002D81 C0E302              <1> 	shl	bl, 2	;;
  7160                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7161 00002D84 81C3[346C0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7162                              <1> 	;push	word [bx+2]		; dpt segment
  7163                              <1> 	;pop	es
  7164                              <1> 	;mov	bx, [bx]		; dpt offset
  7165 00002D8A 8B1B                <1> 	mov	ebx, [ebx]		
  7166                              <1> ;GV_EXIT:
  7167 00002D8C C3                  <1> 	RETn
  7168                              <1> 
  7169                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7170                              <1> hdc1_int: ; 21/02/2015
  7171                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7172                              <1> ;								:
  7173                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7174                              <1> ;								:
  7175                              <1> ;----------------------------------------------------------------
  7176                              <1> 
  7177                              <1> ; 22/12/2014
  7178                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7179                              <1> ;	 '11/15/85'
  7180                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7181                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7182                              <1> 
  7183                              <1> ;int_76h:
  7184                              <1> HD_INT:
  7185                              <1> 	;push	ax
  7186                              <1> 	; 24/12/2021
  7187 00002D8D 50                  <1> 	push	eax
  7188 00002D8E 1E                  <1> 	push	ds
  7189                              <1> 	;CALL	DDS
  7190                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7191 00002D8F 66B81000            <1> 	mov	ax, KDATA
  7192 00002D93 8ED8                <1> 	mov 	ds, ax
  7193                              <1> 	;
  7194                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7195                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7196 00002D95 C605[276C0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7197                              <1> 	;
  7198                              <1> 	;push	dx
  7199                              <1> 	; 24/12/2021
  7200 00002D9C 52                  <1> 	push	edx
  7201 00002D9D 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7202                              <1> 					; Clear Controller
  7203                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7204 00002DA1 EC                  <1> 	in	al, dx			;
  7205                              <1> 	;pop	dx
  7206                              <1> 	; 24/12/2021
  7207 00002DA2 5A                  <1> 	pop	edx
  7208                              <1> 	NEWIODELAY
  2107 00002DA3 E6EB                <2>  out 0EBh,al
  7209                              <1> 	;
  7210 00002DA5 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7211 00002DA7 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7212                              <1> 	;JMP	$+2			; WAIT
  7213                              <1> 	NEWIODELAY
  2107 00002DA9 E6EB                <2>  out 0EBh,al
  7214 00002DAB E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7215 00002DAD 1F                  <1> 	pop	ds
  7216                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7217                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7218                              <1> 	;INT	15H			;  INTERRUPT
  7219                              <1> irq15_iret: ; 25/02/2015
  7220                              <1> 	;pop	ax
  7221                              <1> 	; 24/12/2021
  7222 00002DAE 58                  <1> 	pop	eax
  7223 00002DAF CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7224                              <1> 
  7225                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7226                              <1> hdc2_int: ; 21/02/2015
  7227                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7228                              <1> ;								:
  7229                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7230                              <1> ;								:
  7231                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7232                              <1> 
  7233                              <1> ;int_77h:
  7234                              <1> HD1_INT:
  7235                              <1> 	;push	ax
  7236                              <1> 	; 24/12/2021
  7237 00002DB0 50                  <1> 	push	eax
  7238                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7239                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7240 00002DB1 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7241 00002DB3 E6A0                <1> 	out	0A0h, al
  7242 00002DB5 EB00                <1>         jmp short $+2
  7243 00002DB7 EB00                <1> 	jmp short $+2
  7244 00002DB9 E4A0                <1> 	in	al, 0A0h
  7245 00002DBB 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7246 00002DBD 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7247                              <1> 	;
  7248 00002DBF 1E                  <1> 	push	ds
  7249                              <1> 	;CALL	DDS
  7250                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7251 00002DC0 66B81000            <1> 	mov	ax, KDATA
  7252 00002DC4 8ED8                <1> 	mov 	ds, ax
  7253                              <1> 	;
  7254                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7255                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7256 00002DC6 800D[276C0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7257                              <1> 	;
  7258                              <1> 	;push	dx
  7259                              <1> 	; 24/12/2021
  7260 00002DCD 52                  <1> 	push	edx
  7261 00002DCE 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7262                              <1> 					; Clear Controller (Award BIOS 1999)
  7263 00002DD2 EBCD                <1> 	jmp	short Clear_IRQ1415
  7264                              <1> 
  7265                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7266                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7267                              <1> 
  7268                              <1> ;////////////////////////////////////////////////////////////////////
  7269                              <1> ;; END OF DISK I/O SYTEM ///
  2044                                  %include 'memory.inc'  ; 09/03/2015
  2045                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2046                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.18) - MEMORY.INC
  2047                              <1> ; Last Modification: 03/02/2022 [ 31/12/2021 (Retro UNIX 386 v1.1) ]
  2048                              <1> ;
  2049                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2050                              <1> 
  2051                              <1> ; Ref: Retro UNIX 386 v1.1, Kernel v0.2.1.1 - MEMORY.INC (31/12/2021)
  2052                              <1> 
  2053                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2054                              <1> 
  2055                              <1> ;;04/11/2014 (unix386.s)	
  2056                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2057                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2058                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2059                              <1> ;;
  2060                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2061                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2062                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2063                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2064                              <1> 
  2065                              <1> ; 27/04/2015
  2066                              <1> ; 09/03/2015
  2067                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2068                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2069                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2070                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2071                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2072                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2073                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2074                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2075                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2076                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2077                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2078                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2079                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2080                              <1> SWP_DISK_READ_ERR 	   equ 40
  2081                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2082                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2083                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2084                              <1> SWP_DISK_WRITE_ERR         equ 44
  2085                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2086                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2087                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2088                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2089                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2090                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2091                              <1> 					; (Indicates that the page is not allocated
  2092                              <1> 					; for the process, it is a shared or system
  2093                              <1>                                         ; page, it must not be deallocated!)
  2094                              <1> ; 14/12/2020
  2095                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2096                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2097                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2098                              <1> 				; (Out of memory allocation table)	
  2099                              <1> ;
  2100                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2101                              <1> ;;
  2102                              <1> ;; 10/10/2014
  2103                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2104                              <1> ;;
  2105                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2106                              <1> ;;	(virtual address = physical address)
  2107                              <1> ;; KERNEL PAGE TABLES:
  2108                              <1> ;;	Kernel page directory and all page tables are
  2109                              <1> ;;	on memory as initialized, as equal to physical memory
  2110                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2111                              <1> ;;
  2112                              <1> ;;	what for: User pages may be swapped out, when accessing
  2113                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2114                              <1> ;;	kernel would have to swap it in! But it is also may be
  2115                              <1> ;;	in use by a user process. (In system/kernel mode
  2116                              <1> ;;	kernel can access all memory pages even if they are
  2117                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2118                              <1> ;;	cause conflicts.) 
  2119                              <1> ;;	
  2120                              <1> ;;	As result of these conditions,
  2121                              <1> ;;	all kernel pages must be initialized as equal to 
  2122                              <1> ;;	physical layout for preventing page faults. 
  2123                              <1> ;;	Also, calling "allocate page" procedure after
  2124                              <1> ;;	a page fault can cause another page fault (double fault)
  2125                              <1> ;;	if all kernel page tables would not be initialized.
  2126                              <1> ;;
  2127                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2128                              <1> ;;	memory allocation table. (double word aligned)
  2129                              <1> ;;
  2130                              <1> ;;	[next_page] = first/next free space to be searched
  2131                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2132                              <1> ;;
  2133                              <1> ;;	[last_page] = End of memory (users space), as offset
  2134                              <1> ;;	to memory allocation table. (double word aligned)
  2135                              <1> ;;
  2136                              <1> ;; USER PAGE TABLES:
  2137                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2138                              <1> ;;		'ready only' marked copies of the 
  2139                              <1> ;;		parent process's page table entries (for
  2140                              <1> ;;		same physical memory).
  2141                              <1> ;;		(A page will be copied to a new page after
  2142                              <1> ;;		 if it causes R/W page fault.)
  2143                              <1> ;;
  2144                              <1> ;;	Every user process has own (different)
  2145                              <1> ;;	page directory and page tables.	
  2146                              <1> ;;
  2147                              <1> ;;	Code starts at virtual address 0, always.
  2148                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2149                              <1> ;;	(Programs can be written/developed as simple
  2150                              <1> ;;	 flat memory programs.)
  2151                              <1> ;;
  2152                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2153                              <1> ;;	Memory page will be allocated by kernel only 
  2154                              <1> ;;		(in kernel/system mode only).
  2155                              <1> ;;	* After a
  2156                              <1> ;;	  - 'not present' page fault
  2157                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2158                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2159                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2160                              <1> ;;	  request by running process.
  2161                              <1> ;;	* While creating a process, allocating a new buffer,
  2162                              <1> ;;	  new page tables etc.
  2163                              <1> ;;
  2164                              <1> ;;	At first,
  2165                              <1> ;;	- 'allocate page' procedure will be called;
  2166                              <1> ;,	   if it will return with a valid (>0) physical address
  2167                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2168                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2169                              <1> ;;	- 'allocate page' will be called for allocating page
  2170                              <1> ;;	   directory, page table and running space (data/code).
  2171                              <1> ;;	- every successful 'allocate page' call will decrease
  2172                              <1> ;;	  'free_pages' count (pointer).
  2173                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2174                              <1> ;;	  if 'free_pages' points to a ZERO.
  2175                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2176                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2177                              <1> ;;	  error except errors caused by attribute conflicts.
  2178                              <1> ;;	 (swapper functions)	 
  2179                              <1> ;;					
  2180                              <1> ;;	At second,
  2181                              <1> ;;	- page directory entry will be updated then page table
  2182                              <1> ;;	  entry will be updated.		
  2183                              <1> ;;
  2184                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2185                              <1> ;;	- M.A.T. has a size according to available memory as
  2186                              <1> ;;	  follows:
  2187                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2188                              <1> ;;		  - a bit with value of 0 means allocated page
  2189                              <1> ;;		  - a bit with value of 1 means a free page
  2190                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2191                              <1> ;;	  depending on M.A.T.
  2192                              <1> ;;		(NOTE: Free page count will not be checked
  2193                              <1> ;;		again -on M.A.T.- after initialization. 
  2194                              <1> ;;		Kernel will trust on initial count.)
  2195                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2196                              <1> ;;	  and it will be increased by deallocation procedures.
  2197                              <1> ;;	
  2198                              <1> ;;	- Available memory will be calculated during
  2199                              <1> ;;	  the kernel's initialization stage (in real mode).
  2200                              <1> ;;	  Memory allocation table and kernel page tables 
  2201                              <1> ;;	  will be formatted/sized as result of available
  2202                              <1> ;;	  memory calculation before paging is enabled.
  2203                              <1> ;;
  2204                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2205                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2206                              <1> ;;	- Memory allocation for kernel page directory size 
  2207                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2208                              <1> ;;	  for page tables)
  2209                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2210                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2211                              <1> ;;	- User (available) space will be started 
  2212                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2213                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2214                              <1> ;;	  memory allocation table and kernel's page directory
  2215                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2216                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2217                              <1> ;; 	  for buffers.
  2218                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2219                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2220                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2221                              <1> ;;
  2222                              <1> ;; For 1GB Available Memory:
  2223                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2224                              <1> ;;	- Memory allocation for kernel page directory size 
  2225                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2226                              <1> ;;	  for page tables)
  2227                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2228                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2229                              <1> ;;	- User (available) space will be started 
  2230                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2231                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2232                              <1> ;;	  memory allocation table and kernel's page directory
  2233                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2234                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2235                              <1> ;; 	  for buffers.
  2236                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2237                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2238                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2239                              <1> ;;
  2240                              <1> ;;
  2241                              <1> 
  2242                              <1> ;;************************************************************************************
  2243                              <1> ;; 
  2244                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2245                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2246                              <1> 
  2247                              <1> ;; Main factor: "sys fork" system call 
  2248                              <1> ;;	
  2249                              <1> ;; 		FORK
  2250                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2251                              <1> ;;  writable pages ---->|
  2252                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2253                              <1> ;; 
  2254                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2255                              <1> ;; 
  2256                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2257                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2258                              <1> ;;       -while R/W bit is 0-. 
  2259                              <1> ;; 
  2260                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2261                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2262                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2263                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2264                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2265                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2266                              <1> ;; 
  2267                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2268                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2269                              <1> ;;   Parent's PTE attributes are not changed.
  2270                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2271                              <1> ;;    destroy/mix previous fork result).
  2272                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2273                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2274                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2275                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2276                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2277                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2278                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2279                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2280                              <1> ;; 
  2281                              <1> ;; !? WHAT FOR (duplication after duplication):
  2282                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2283                              <1> ;; program/executable code continues from specified location as child process, 
  2284                              <1> ;; returns back previous code location as parent process, every child after 
  2285                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2286                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2287                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2288                              <1> ;; was copied to child's process segment (all of code and data) according to
  2289                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2290                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2291                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2292                              <1> ;; (complete running image of parent process) to the child process; 
  2293                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2294                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2295                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2296                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2297                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2298                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2299                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2300                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2301                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2302                              <1> ;; for sharing same read only pages between parent and child processes.
  2303                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2304                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2305                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2306                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2307                              <1> ;; -deallocation problem-.
  2308                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2309                              <1> ;; 
  2310                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2311                              <1> ;; # Page fault handler will do those:
  2312                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2313                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2314                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2315                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2316                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2317                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2318                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2319                              <1> ;;     to child process.)	
  2320                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2321                              <1> ;; # Page fault handler will do those:
  2322                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2323                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2324                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2325                              <1> ;;     address or not. 
  2326                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2327                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2328                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2329                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2330                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2331                              <1> ;; 
  2332                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2333                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2334                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2335                              <1> ;;       duplication method details, it is not possible multiple child processes
  2336                              <1> ;;       were using same page with duplicated PTEs.
  2337                              <1> ;; 
  2338                              <1> ;;************************************************************************************   
  2339                              <1> 
  2340                              <1> ;; 08/10/2014
  2341                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2342                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2343                              <1> 
  2344                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2345                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2346                              <1> ;; (25/08/2014, Revision: 5057) file 
  2347                              <1> ;; by KolibriOS Team (2004-2012)
  2348                              <1> 
  2349                              <1> allocate_page:
  2350                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2351                              <1> 	; 01/07/2015
  2352                              <1> 	; 05/05/2015
  2353                              <1> 	; 30/04/2015
  2354                              <1> 	; 16/10/2014
  2355                              <1> 	; 08/10/2014
  2356                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2357                              <1> 	;
  2358                              <1> 	; INPUT -> none
  2359                              <1> 	;
  2360                              <1> 	; OUTPUT ->
  2361                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2362                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2363                              <1> 	;
  2364                              <1> 	;	CF = 1 and EAX = 0 
  2365                              <1> 	; 		   if there is not a free page to be allocated	
  2366                              <1> 	;
  2367                              <1> 	; Modified Registers -> none (except EAX)
  2368                              <1> 	;
  2369 00002DD4 A1[A06B0000]        <1> 	mov	eax, [free_pages]
  2370 00002DD9 21C0                <1> 	and	eax, eax
  2371 00002DDB 7438                <1> 	jz	short out_of_memory
  2372                              <1> 	;
  2373 00002DDD 53                  <1> 	push	ebx
  2374 00002DDE 51                  <1> 	push	ecx
  2375                              <1> 	;
  2376 00002DDF BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2377 00002DE4 89D9                <1> 	mov	ecx, ebx
  2378                              <1>  				     ; NOTE: 32 (first_page) is initial
  2379                              <1> 				     ; value of [next_page].
  2380                              <1> 				     ; It points to the first available
  2381                              <1> 				     ; page block for users (ring 3) ...	
  2382                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2383                              <1> 				     ; (at the of the first 4 MB)		
  2384 00002DE6 031D[A46B0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2385                              <1> 				 ; next_free_page >> 5
  2386 00002DEC 030D[A86B0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2387                              <1> 				 ; (total_pages - 1) >> 5
  2388                              <1> al_p_scan:
  2389 00002DF2 39CB                <1> 	cmp	ebx, ecx
  2390 00002DF4 770A                <1> 	ja	short al_p_notfound
  2391                              <1> 	;
  2392                              <1> 	; 01/07/2015
  2393                              <1> 	; AMD64 Architecture Programmers Manual
  2394                              <1> 	; Volume 3:
  2395                              <1> 	; General-Purpose and System Instructions
  2396                              <1> 	;
  2397                              <1> 	; BSF - Bit Scan Forward
  2398                              <1> 	;
  2399                              <1> 	;   Searches the value in a register or a memory location
  2400                              <1> 	;   (second operand) for the least-significant set bit. 
  2401                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2402                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2403                              <1> 	;   register (first operand). If the second operand contains 0, 
  2404                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2405                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2406                              <1> 	;   of the searched value
  2407                              <1> 	;
  2408 00002DF6 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2409                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2410                              <1> 			   ; loads the destination with an index to
  2411                              <1> 			   ; first set bit. (0 -> 31) 
  2412                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2413 00002DF9 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2414                              <1> 			 ;
  2415                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2416                              <1> 			 ;	  with value of 1 means 
  2417                              <1> 			 ;	  the corresponding page is free 
  2418                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2419 00002DFB 83C304              <1> 	add	ebx, 4
  2420                              <1> 			 ; We return back for searching next page block
  2421                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2422                              <1> 			 ;	 we always will find at least 1 free page here.
  2423 00002DFE EBF2                <1>         jmp     short al_p_scan
  2424                              <1> 	;
  2425                              <1> al_p_notfound:
  2426 00002E00 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2427 00002E06 890D[A46B0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2428                              <1> 				 ; (deallocate_page procedure will change it)
  2429 00002E0C 31C0                <1> 	xor	eax, eax
  2430 00002E0E A3[A06B0000]        <1> 	mov	[free_pages], eax ; 0
  2431 00002E13 59                  <1> 	pop	ecx
  2432 00002E14 5B                  <1> 	pop	ebx
  2433                              <1> 	;
  2434                              <1> ; 24/12/2021
  2435                              <1> ; ('swap_out' procedure call is disabled)
  2436                              <1> 
  2437                              <1> out_of_memory:
  2438                              <1> ;	call	swap_out
  2439                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2440                              <1> ;	;
  2441                              <1> ;	sub 	eax, eax ; 0
  2442 00002E15 F9                  <1> 	stc
  2443 00002E16 C3                  <1> 	retn
  2444                              <1> 
  2445                              <1> al_p_found:
  2446 00002E17 89D9                <1> 	mov	ecx, ebx
  2447 00002E19 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2448 00002E1F 890D[A46B0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2449                              <1> 				 ; address/offset (to the next)
  2450 00002E25 FF0D[A06B0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2451                              <1> 	;
  2452 00002E2B 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2453                              <1> 				 ; is copied into the Carry Flag and then cleared
  2454                              <1> 				 ; in the destination.
  2455                              <1> 				 ;
  2456                              <1> 				 ; Reset the bit which is corresponding to the 
  2457                              <1> 				 ; (just) allocated page.
  2458                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2459 00002E2E C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2460 00002E31 01C8                <1> 	add	eax, ecx	 ; = page number
  2461 00002E33 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2462                              <1> 	; EAX = physical address of memory page
  2463                              <1> 	;
  2464                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2465                              <1> 	;       according to this EAX value...
  2466 00002E36 59                  <1> 	pop	ecx
  2467 00002E37 5B                  <1> 	pop	ebx
  2468                              <1> al_p_ok:
  2469 00002E38 C3                  <1> 	retn
  2470                              <1> 
  2471                              <1> make_page_dir:
  2472                              <1> 	; 18/04/2015
  2473                              <1> 	; 12/04/2015
  2474                              <1> 	; 23/10/2014
  2475                              <1> 	; 16/10/2014
  2476                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2477                              <1> 	;
  2478                              <1> 	; INPUT ->
  2479                              <1> 	;	none
  2480                              <1> 	; OUTPUT ->
  2481                              <1> 	;	(EAX = 0)
  2482                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2483                              <1> 	;	cf = 0 ->
  2484                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2485                              <1> 	;		  process/user.
  2486                              <1> 	;
  2487                              <1> 	; Modified Registers -> EAX
  2488                              <1> 	;
  2489 00002E39 E896FFFFFF          <1> 	call	allocate_page
  2490 00002E3E 7216                <1> 	jc	short mkpd_error
  2491                              <1> 	;
  2492 00002E40 A3[AF6F0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2493                              <1> 				  ; (Physical address)
  2494                              <1> clear_page:
  2495                              <1> 	; 18/04/2015
  2496                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2497                              <1> 	;
  2498                              <1> 	; INPUT ->
  2499                              <1> 	;	EAX = physical address of the page
  2500                              <1> 	; OUTPUT ->
  2501                              <1> 	;	all bytes of the page will be cleared
  2502                              <1> 	;
  2503                              <1> 	; Modified Registers -> none
  2504                              <1> 	;
  2505 00002E45 57                  <1> 	push	edi
  2506 00002E46 51                  <1> 	push	ecx
  2507 00002E47 50                  <1> 	push	eax
  2508 00002E48 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2509 00002E4D 89C7                <1> 	mov	edi, eax
  2510 00002E4F 31C0                <1> 	xor	eax, eax
  2511 00002E51 F3AB                <1> 	rep	stosd
  2512 00002E53 58                  <1> 	pop	eax
  2513 00002E54 59                  <1> 	pop	ecx
  2514 00002E55 5F                  <1> 	pop	edi
  2515                              <1> mkpd_error:
  2516                              <1> mkpt_error:
  2517 00002E56 C3                  <1> 	retn
  2518                              <1> 
  2519                              <1> make_page_table:
  2520                              <1> 	; 23/06/2015
  2521                              <1> 	; 18/04/2015
  2522                              <1> 	; 12/04/2015
  2523                              <1> 	; 16/10/2014
  2524                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2525                              <1> 	;
  2526                              <1> 	; INPUT ->
  2527                              <1> 	;	EBX = virtual (linear) address
  2528                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2529                              <1> 	;	      (higher 20 bits must be ZERO)
  2530                              <1> 	;	      (bit 0 must be 1)	 
  2531                              <1> 	;	u.pgdir = page directory (physical) address
  2532                              <1> 	; OUTPUT ->
  2533                              <1> 	;	EDX = Page directory entry address
  2534                              <1> 	;	EAX = Page table address
  2535                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2536                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2537                              <1> 	;
  2538                              <1> 	; Modified Registers -> EAX, EDX
  2539                              <1> 	;
  2540 00002E57 E878FFFFFF          <1> 	call	allocate_page
  2541 00002E5C 72F8                <1> 	jc	short mkpt_error
  2542 00002E5E E811000000          <1> 	call	set_pde	
  2543 00002E63 EBE0                <1> 	jmp	short clear_page
  2544                              <1> 
  2545                              <1> make_page:
  2546                              <1> 	; 24/07/2015
  2547                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2548                              <1> 	;
  2549                              <1> 	; INPUT ->
  2550                              <1> 	;	EBX = virtual (linear) address
  2551                              <1> 	;	ECX = page attributes (lower 12 bits)
  2552                              <1> 	;	      (higher 20 bits must be ZERO)
  2553                              <1> 	;	      (bit 0 must be 1)	 
  2554                              <1> 	;	u.pgdir = page directory (physical) address
  2555                              <1> 	; OUTPUT ->
  2556                              <1> 	;	EBX = Virtual address
  2557                              <1> 	;	(EDX = PTE value)
  2558                              <1> 	;	EAX = Physical address
  2559                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2560                              <1> 	;
  2561                              <1> 	; Modified Registers -> EAX, EDX
  2562                              <1> 	;
  2563 00002E65 E86AFFFFFF          <1> 	call	allocate_page
  2564 00002E6A 7207                <1> 	jc	short mkp_err
  2565 00002E6C E821000000          <1> 	call	set_pte	
  2566 00002E71 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2567                              <1> mkp_err:
  2568 00002E73 C3                  <1> 	retn
  2569                              <1> 
  2570                              <1> set_pde:	; Set page directory entry (PDE)
  2571                              <1> 	; 20/07/2015
  2572                              <1> 	; 18/04/2015
  2573                              <1> 	; 12/04/2015
  2574                              <1> 	; 23/10/2014
  2575                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2576                              <1> 	;
  2577                              <1> 	; INPUT ->
  2578                              <1> 	;	EAX = physical address
  2579                              <1> 	;	      (use present value if EAX = 0)
  2580                              <1> 	;	EBX = virtual (linear) address
  2581                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2582                              <1> 	;	      (higher 20 bits must be ZERO)
  2583                              <1> 	;	      (bit 0 must be 1)	 
  2584                              <1> 	;	u.pgdir = page directory (physical) address
  2585                              <1> 	; OUTPUT ->
  2586                              <1> 	;	EDX = PDE address
  2587                              <1> 	;	EAX = page table address (physical)
  2588                              <1> 	;	;(CF=1 -> Invalid page address)
  2589                              <1> 	;
  2590                              <1> 	; Modified Registers -> EDX
  2591                              <1> 	;
  2592 00002E74 89DA                <1> 	mov	edx, ebx
  2593 00002E76 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2594 00002E79 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2595 00002E7C 0315[AF6F0000]      <1> 	add	edx, [u.pgdir]
  2596                              <1> 	;
  2597 00002E82 21C0                <1> 	and	eax, eax
  2598 00002E84 7506                <1> 	jnz	short spde_1
  2599                              <1> 	;
  2600 00002E86 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2601                              <1> 	;test	al, 1
  2602                              <1> 	;jz	short spde_2
  2603 00002E88 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2604                              <1> spde_1:
  2605                              <1> 	;and	cx, 0FFFh
  2606 00002E8C 8902                <1> 	mov	[edx], eax
  2607 00002E8E 66090A              <1> 	or	[edx], cx
  2608 00002E91 C3                  <1> 	retn
  2609                              <1> ;spde_2: ; error
  2610                              <1> ;	stc
  2611                              <1> ;	retn
  2612                              <1> 
  2613                              <1> set_pte:	; Set page table entry (PTE)
  2614                              <1> 	; 24/07/2015
  2615                              <1> 	; 20/07/2015
  2616                              <1> 	; 23/06/2015
  2617                              <1> 	; 18/04/2015
  2618                              <1> 	; 12/04/2015
  2619                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2620                              <1> 	;
  2621                              <1> 	; INPUT ->
  2622                              <1> 	;	EAX = physical page address
  2623                              <1> 	;	      (use present value if EAX = 0)
  2624                              <1> 	;	EBX = virtual (linear) address
  2625                              <1> 	;	ECX = page attributes (lower 12 bits)
  2626                              <1> 	;	      (higher 20 bits must be ZERO)
  2627                              <1> 	;	      (bit 0 must be 1)	 
  2628                              <1> 	;	u.pgdir = page directory (physical) address
  2629                              <1> 	; OUTPUT ->
  2630                              <1> 	;	EAX = physical page address
  2631                              <1> 	;	(EDX = PTE value)
  2632                              <1> 	;	EBX = virtual address
  2633                              <1> 	;
  2634                              <1> 	;	CF = 1 -> error
  2635                              <1> 	;
  2636                              <1> 	; Modified Registers -> EAX, EDX
  2637                              <1> 	;
  2638 00002E92 50                  <1> 	push	eax
  2639 00002E93 A1[AF6F0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2640 00002E98 E837000000          <1> 	call 	get_pde
  2641                              <1> 		; EDX = PDE address
  2642                              <1> 		; EAX = PDE value
  2643 00002E9D 5A                  <1> 	pop	edx ; physical page address
  2644 00002E9E 722A                <1> 	jc	short spte_err ; PDE not present
  2645                              <1> 	;
  2646 00002EA0 53                  <1> 	push	ebx ; 24/07/2015
  2647 00002EA1 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2648                              <1> 			    ; EDX = PT address (physical)	
  2649 00002EA5 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2650 00002EA8 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2651                              <1> 			 ; clear higher 10 bits (PD bits)
  2652 00002EAE C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2653 00002EB1 01C3                <1> 	add	ebx, eax
  2654                              <1> 	;
  2655 00002EB3 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2656 00002EB5 A801                <1> 	test	al, 1
  2657 00002EB7 740C                <1> 	jz	short spte_0
  2658 00002EB9 09D2                <1> 	or	edx, edx
  2659 00002EBB 750F                <1> 	jnz	short spte_1
  2660 00002EBD 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2661 00002EC1 89C2                <1> 	mov	edx, eax
  2662 00002EC3 EB09                <1> 	jmp	short spte_2	
  2663                              <1> spte_0:
  2664                              <1> 	; If this PTE contains a swap (disk) address,
  2665                              <1> 	; it can be updated by using 'swap_in' procedure
  2666                              <1> 	; only!
  2667 00002EC5 21C0                <1> 	and	eax, eax
  2668 00002EC7 7403                <1> 	jz	short spte_1
  2669                              <1> 	; 24/07/2015
  2670                              <1> 	; swapped page ! (on disk)
  2671 00002EC9 5B                  <1> 	pop	ebx
  2672                              <1> spte_err:
  2673 00002ECA F9                  <1> 	stc
  2674 00002ECB C3                  <1> 	retn
  2675                              <1> spte_1: 
  2676 00002ECC 89D0                <1> 	mov	eax, edx
  2677                              <1> spte_2:
  2678 00002ECE 09CA                <1> 	or	edx, ecx
  2679                              <1> 	; 23/06/2015
  2680 00002ED0 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2681                              <1> 	; 24/07/2015
  2682 00002ED2 5B                  <1> 	pop	ebx
  2683 00002ED3 C3                  <1> 	retn
  2684                              <1> 
  2685                              <1> get_pde:	; Get present value of the relevant PDE
  2686                              <1> 	; 20/07/2015
  2687                              <1> 	; 18/04/2015
  2688                              <1> 	; 12/04/2015
  2689                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2690                              <1> 	;
  2691                              <1> 	; INPUT ->
  2692                              <1> 	;	EBX = virtual (linear) address
  2693                              <1> 	;	EAX = page directory (physical) address
  2694                              <1> 	; OUTPUT ->
  2695                              <1> 	;	EDX = Page directory entry address
  2696                              <1> 	;	EAX = Page directory entry value
  2697                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2698                              <1> 	; Modified Registers -> EDX, EAX
  2699                              <1> 	;
  2700 00002ED4 89DA                <1> 	mov	edx, ebx
  2701 00002ED6 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2702 00002ED9 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2703 00002EDC 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2704 00002EDE 8B02                <1> 	mov	eax, [edx]
  2705 00002EE0 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2706 00002EE2 751F                <1> 	jnz	short gpte_retn
  2707 00002EE4 F9                  <1> 	stc
  2708                              <1> gpde_retn:	
  2709 00002EE5 C3                  <1> 	retn
  2710                              <1> 
  2711                              <1> get_pte:
  2712                              <1> 		; Get present value of the relevant PTE
  2713                              <1> 	; 29/07/2015
  2714                              <1> 	; 20/07/2015
  2715                              <1> 	; 18/04/2015
  2716                              <1> 	; 12/04/2015
  2717                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2718                              <1> 	;
  2719                              <1> 	; INPUT ->
  2720                              <1> 	;	EBX = virtual (linear) address
  2721                              <1> 	;	EAX = page directory (physical) address
  2722                              <1> 	; OUTPUT ->
  2723                              <1> 	;	EDX = Page table entry address (if CF=0)
  2724                              <1> 	;	      Page directory entry address (if CF=1)
  2725                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2726                              <1> 	;	EAX = Page table entry value (page address)
  2727                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2728                              <1> 	; Modified Registers -> EAX, EDX
  2729                              <1> 	;
  2730 00002EE6 E8E9FFFFFF          <1> 	call 	get_pde
  2731 00002EEB 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2732                              <1> 	;jnc	short gpte_1
  2733                              <1> 	;retn
  2734                              <1> ;gpte_1:
  2735 00002EED 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2736 00002EF1 89DA                <1> 	mov	edx, ebx
  2737 00002EF3 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2738 00002EF6 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2739                              <1> 			 ; clear higher 10 bits (PD bits)
  2740 00002EFC C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2741 00002EFF 01C2                <1> 	add	edx, eax
  2742 00002F01 8B02                <1> 	mov	eax, [edx]
  2743                              <1> gpte_retn:
  2744 00002F03 C3                  <1> 	retn
  2745                              <1> 
  2746                              <1> deallocate_page_dir:
  2747                              <1> 	; 15/09/2015
  2748                              <1> 	; 05/08/2015
  2749                              <1> 	; 30/04/2015
  2750                              <1> 	; 28/04/2015
  2751                              <1> 	; 17/10/2014
  2752                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2753                              <1> 	;
  2754                              <1> 	; INPUT ->
  2755                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2756                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2757                              <1> 	; OUTPUT ->
  2758                              <1> 	;	All of page tables in the page directory
  2759                              <1> 	;	and page dir's itself will be deallocated
  2760                              <1> 	;	except 'read only' duplicated pages (will be converted
  2761                              <1> 	;	to writable pages).
  2762                              <1> 	;
  2763                              <1> 	; Modified Registers -> EAX
  2764                              <1> 	;
  2765                              <1> 	;
  2766 00002F04 56                  <1> 	push	esi
  2767 00002F05 51                  <1> 	push	ecx
  2768 00002F06 50                  <1> 	push	eax
  2769 00002F07 89C6                <1> 	mov	esi, eax 
  2770 00002F09 31C9                <1> 	xor	ecx, ecx
  2771                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2772                              <1> 	; it must not be deallocated
  2773 00002F0B 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2774                              <1> dapd_0:
  2775 00002F0D AD                  <1> 	lodsd
  2776 00002F0E A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2777 00002F10 7409                <1> 	jz	short dapd_1	
  2778 00002F12 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2779 00002F16 E812000000          <1> 	call	deallocate_page_table			
  2780                              <1> dapd_1:
  2781 00002F1B 41                  <1> 	inc	ecx ; page directory entry index
  2782 00002F1C 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2783 00002F22 72E9                <1> 	jb	short dapd_0
  2784                              <1> dapd_2:
  2785 00002F24 58                  <1> 	pop	eax
  2786 00002F25 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2787 00002F2A 59                  <1> 	pop	ecx
  2788 00002F2B 5E                  <1> 	pop	esi
  2789 00002F2C C3                  <1> 	retn
  2790                              <1> 
  2791                              <1> deallocate_page_table:
  2792                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2793                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2794                              <1> 	; 19/09/2015
  2795                              <1> 	; 15/09/2015
  2796                              <1> 	; 05/08/2015
  2797                              <1> 	; 30/04/2015
  2798                              <1> 	; 28/04/2015
  2799                              <1> 	; 24/10/2014
  2800                              <1> 	; 23/10/2014
  2801                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2802                              <1> 	;
  2803                              <1> 	; INPUT ->
  2804                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2805                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2806                              <1> 	;	(ECX = page directory entry index)
  2807                              <1> 	; OUTPUT ->
  2808                              <1> 	;	All of pages in the page table and page table's itself
  2809                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2810                              <1> 	;	(will be converted to writable pages).
  2811                              <1> 	;
  2812                              <1> 	; Modified Registers -> EAX
  2813                              <1> 	;
  2814 00002F2D 56                  <1> 	push	esi
  2815 00002F2E 57                  <1> 	push	edi
  2816 00002F2F 52                  <1> 	push	edx
  2817 00002F30 50                  <1> 	push	eax ; *
  2818 00002F31 89C6                <1> 	mov	esi, eax 
  2819 00002F33 31FF                <1> 	xor	edi, edi ; 0
  2820                              <1> dapt_0:
  2821 00002F35 AD                  <1> 	lodsd
  2822 00002F36 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2823 00002F38 7455                <1> 	jz	short dapt_1
  2824                              <1> 	;
  2825 00002F3A A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2826                              <1> 				  ; (must be 1)
  2827 00002F3C 753F                <1> 	jnz	short dapt_3
  2828                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2829 00002F3E 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2830                              <1> 				   ; as child's page ?
  2831 00002F42 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2832                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2833                              <1> 	; ECX = page directory entry index (0-1023)
  2834 00002F44 53                  <1> 	push	ebx
  2835 00002F45 51                  <1> 	push	ecx
  2836 00002F46 66C1E102            <1> 	shl	cx, 2 ; *4 
  2837 00002F4A 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2838 00002F4C 8B0B                <1> 	mov	ecx, [ebx]
  2839 00002F4E F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2840 00002F51 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2841 00002F53 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2842                              <1> 	; EDI = page table entry index (0-1023)
  2843 00002F58 89FA                <1> 	mov	edx, edi 
  2844 00002F5A 66C1E202            <1> 	shl	dx, 2 ; *4 
  2845 00002F5E 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2846 00002F60 8B1A                <1> 	mov	ebx, [edx]
  2847 00002F62 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2848 00002F65 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2849 00002F67 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2850 00002F6B 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2851 00002F70 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2852 00002F72 7507                <1> 	jne	short dapt_2	; not same page
  2853                              <1> 				; deallocate the child's page
  2854 00002F74 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2855 00002F77 59                  <1> 	pop	ecx
  2856 00002F78 5B                  <1> 	pop	ebx
  2857 00002F79 EB0D                <1> 	jmp	short dapt_4
  2858                              <1> 
  2859                              <1> ; 24/12/2021
  2860                              <1> ; ('dapt_1' is disabled)
  2861                              <1> ;
  2862                              <1> ;dapt_1:
  2863                              <1> ;	or	eax, eax	; swapped page ?
  2864                              <1> ;	jz	short dapt_5	; no
  2865                              <1> ;				; yes
  2866                              <1> ;	shr	eax, 1
  2867                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2868                              <1> ;				  ; on the swap disk (or in file)
  2869                              <1> ;	jmp	short dapt_5
  2870                              <1> dapt_2:
  2871 00002F7B 59                  <1> 	pop	ecx
  2872 00002F7C 5B                  <1> 	pop	ebx
  2873                              <1> dapt_3:	
  2874                              <1> 	; 12/07/2016
  2875 00002F7D 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2876 00002F81 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2877                              <1> 	;
  2878                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2879 00002F83 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2880                              <1> dapt_4:
  2881 00002F88 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2882                              <1> dapt_1:	; 24/12/2021
  2883                              <1> dapt_5:
  2884 00002F8F 47                  <1> 	inc	edi ; page table entry index
  2885 00002F90 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2886 00002F96 729D                <1> 	jb	short dapt_0
  2887                              <1> 	;
  2888 00002F98 58                  <1> 	pop	eax ; *
  2889 00002F99 5A                  <1> 	pop	edx
  2890 00002F9A 5F                  <1> 	pop	edi	
  2891 00002F9B 5E                  <1> 	pop	esi
  2892                              <1> 	;
  2893                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2894                              <1> 	;retn
  2895                              <1> 
  2896                              <1> deallocate_page:
  2897                              <1> 	; 15/09/2015
  2898                              <1> 	; 28/04/2015
  2899                              <1> 	; 10/03/2015
  2900                              <1> 	; 17/10/2014
  2901                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2902                              <1> 	;
  2903                              <1> 	; INPUT -> 
  2904                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2905                              <1> 	; OUTPUT ->
  2906                              <1> 	;	[free_pages] is increased
  2907                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2908                              <1> 	;	CF = 1 if the page is already deallocated
  2909                              <1> 	; 	       (or not allocated) before.  
  2910                              <1> 	;
  2911                              <1> 	; Modified Registers -> EAX
  2912                              <1> 	;
  2913 00002F9C 53                  <1> 	push	ebx
  2914 00002F9D 52                  <1> 	push	edx
  2915                              <1> 	;
  2916 00002F9E C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2917                              <1> 				     ; 12 bits right
  2918                              <1> 				     ; to get page number
  2919 00002FA1 89C2                <1> 	mov	edx, eax
  2920                              <1> 	; 15/09/2015
  2921 00002FA3 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2922                              <1> 				     ; (1 allocation bit = 1 page)
  2923                              <1> 				     ; (1 allocation bytes = 8 pages)
  2924 00002FA6 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2925                              <1> 				     ; (to get 32 bit position)			
  2926                              <1> 	;
  2927 00002FA9 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2928 00002FAE 01D3                <1> 	add	ebx, edx
  2929 00002FB0 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2930                              <1> 				     ; (allocation bit position)	 
  2931 00002FB3 3B15[A46B0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2932                              <1> 				     ; than the address in 'next_page' ?
  2933                              <1> 				     ; (next/first free page value)		
  2934 00002FB9 7306                <1> 	jnb	short dap_1	     ; no	
  2935 00002FBB 8915[A46B0000]      <1> 	mov	[next_page], edx     ; yes
  2936                              <1> dap_1:
  2937 00002FC1 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2938                              <1> 				     ; set relevant bit to 1.
  2939                              <1> 				     ; set CF to the previous bit value	
  2940                              <1> 	;cmc			     ; complement carry flag	
  2941                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2942                              <1> 				     ; if the page is already deallocated
  2943                              <1> 				     ; before.	
  2944 00002FC4 FF05[A06B0000]      <1>         inc     dword [free_pages]
  2945                              <1> dap_2:
  2946 00002FCA 5A                  <1> 	pop	edx
  2947 00002FCB 5B                  <1> 	pop	ebx
  2948 00002FCC C3                  <1> 	retn
  2949                              <1> 
  2950                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2951                              <1> ;;                                                              ;;
  2952                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2953                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2954                              <1> ;;                                                              ;;
  2955                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2956                              <1> 
  2957                              <1> ;;$Revision: 5057 $
  2958                              <1> 
  2959                              <1> 
  2960                              <1> ;;align 4
  2961                              <1> ;;proc alloc_page
  2962                              <1> 
  2963                              <1> ;;        pushfd
  2964                              <1> ;;        cli
  2965                              <1> ;;        push    ebx
  2966                              <1> ;;;//-
  2967                              <1> ;;        cmp     [pg_data.pages_free], 1
  2968                              <1> ;;        jle     .out_of_memory
  2969                              <1> ;;;//-
  2970                              <1> ;;
  2971                              <1> ;;        mov     ebx, [page_start]
  2972                              <1> ;;        mov     ecx, [page_end]
  2973                              <1> ;;.l1:
  2974                              <1> ;;        bsf     eax, [ebx];
  2975                              <1> ;;        jnz     .found
  2976                              <1> ;;        add     ebx, 4
  2977                              <1> ;;        cmp     ebx, ecx
  2978                              <1> ;;        jb      .l1
  2979                              <1> ;;        pop     ebx
  2980                              <1> ;;        popfd
  2981                              <1> ;;        xor     eax, eax
  2982                              <1> ;;        ret
  2983                              <1> ;;.found:
  2984                              <1> ;;;//-
  2985                              <1> ;;        dec     [pg_data.pages_free]
  2986                              <1> ;;        jz      .out_of_memory
  2987                              <1> ;;;//-
  2988                              <1> ;;        btr     [ebx], eax
  2989                              <1> ;;        mov     [page_start], ebx
  2990                              <1> ;;        sub     ebx, sys_pgmap
  2991                              <1> ;;        lea     eax, [eax+ebx*8]
  2992                              <1> ;;        shl     eax, 12
  2993                              <1> ;;;//-       dec [pg_data.pages_free]
  2994                              <1> ;;        pop     ebx
  2995                              <1> ;;        popfd
  2996                              <1> ;;        ret
  2997                              <1> ;;;//-
  2998                              <1> ;;.out_of_memory:
  2999                              <1> ;;        mov     [pg_data.pages_free], 1
  3000                              <1> ;;        xor     eax, eax
  3001                              <1> ;;        pop     ebx
  3002                              <1> ;;        popfd
  3003                              <1> ;;        ret
  3004                              <1> ;;;//-
  3005                              <1> ;;endp
  3006                              <1> 
  3007                              <1> duplicate_page_dir:
  3008                              <1> 	; 21/09/2015
  3009                              <1> 	; 31/08/2015
  3010                              <1> 	; 20/07/2015
  3011                              <1> 	; 28/04/2015
  3012                              <1> 	; 27/04/2015
  3013                              <1> 	; 18/04/2015
  3014                              <1> 	; 12/04/2015
  3015                              <1> 	; 18/10/2014
  3016                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3017                              <1> 	;
  3018                              <1> 	; INPUT -> 
  3019                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3020                              <1> 	;		    page directory.
  3021                              <1> 	; OUTPUT ->
  3022                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3023                              <1> 	;	       page directory.
  3024                              <1> 	;	(New page directory with new page table entries.)
  3025                              <1> 	;	(New page tables with read only copies of the parent's
  3026                              <1> 	;	pages.)
  3027                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3028                              <1> 	;
  3029                              <1> 	; Modified Registers -> none (except EAX)
  3030                              <1> 	;
  3031 00002FCD E802FEFFFF          <1> 	call	allocate_page
  3032 00002FD2 723E                <1> 	jc	short dpd_err
  3033                              <1> 	;
  3034 00002FD4 55                  <1> 	push	ebp ; 20/07/2015
  3035 00002FD5 56                  <1> 	push	esi
  3036 00002FD6 57                  <1> 	push	edi
  3037 00002FD7 53                  <1> 	push	ebx
  3038 00002FD8 51                  <1> 	push	ecx
  3039 00002FD9 8B35[AF6F0000]      <1> 	mov	esi, [u.pgdir]
  3040 00002FDF 89C7                <1> 	mov	edi, eax
  3041 00002FE1 50                  <1> 	push	eax ; save child's page directory address
  3042                              <1> 	; 31/08/2015
  3043                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3044                              <1> 	; (use same system space for all user page tables) 
  3045 00002FE2 A5                  <1> 	movsd
  3046 00002FE3 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3047 00002FE8 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3048                              <1> dpd_0:	
  3049 00002FED AD                  <1> 	lodsd
  3050                              <1> 	;or	eax, eax
  3051                              <1>         ;jnz     short dpd_1
  3052 00002FEE A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3053 00002FF0 7508                <1> 	jnz	short dpd_1
  3054                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3055 00002FF2 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3056 00002FF8 EB0F                <1> 	jmp	short dpd_2
  3057                              <1> dpd_1:	
  3058 00002FFA 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3059 00002FFE 89C3                <1> 	mov	ebx, eax
  3060                              <1> 	; EBX = Parent's page table address
  3061 00003000 E81F000000          <1> 	call	duplicate_page_table
  3062 00003005 720C                <1> 	jc	short dpd_p_err
  3063                              <1> 	; EAX = Child's page table address
  3064 00003007 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3065                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3066                              <1> 			 ; (present, writable, user)
  3067                              <1> dpd_2:
  3068 00003009 AB                  <1> 	stosd
  3069 0000300A E2E1                <1> 	loop	dpd_0
  3070                              <1> 	;
  3071 0000300C 58                  <1> 	pop	eax  ; restore child's page directory address
  3072                              <1> dpd_3:
  3073 0000300D 59                  <1> 	pop	ecx
  3074 0000300E 5B                  <1> 	pop	ebx
  3075 0000300F 5F                  <1> 	pop	edi
  3076 00003010 5E                  <1> 	pop	esi
  3077 00003011 5D                  <1> 	pop	ebp ; 20/07/2015
  3078                              <1> dpd_err:
  3079 00003012 C3                  <1> 	retn
  3080                              <1> dpd_p_err:
  3081                              <1> 	; release the allocated pages missing (recover free space)
  3082 00003013 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3083 00003014 8B1D[AF6F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3084 0000301A E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3085 0000301F 29C0                <1> 	sub	eax, eax ; 0
  3086 00003021 F9                  <1> 	stc
  3087 00003022 EBE9                <1> 	jmp	short dpd_3	
  3088                              <1> 
  3089                              <1> duplicate_page_table:
  3090                              <1> 	; 31/12/2021
  3091                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3092                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3093                              <1> 	; 21/09/2015
  3094                              <1> 	; 20/07/2015
  3095                              <1> 	; 05/05/2015
  3096                              <1> 	; 28/04/2015
  3097                              <1> 	; 27/04/2015
  3098                              <1> 	; 18/04/2015
  3099                              <1> 	; 18/10/2014
  3100                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3101                              <1> 	;
  3102                              <1> 	; INPUT -> 
  3103                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3104                              <1> 	;       20/02/2017		 
  3105                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3106                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3107                              <1> 	; OUTPUT ->
  3108                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3109                              <1> 	;	      (with 'read only' attribute of page table entries)
  3110                              <1> 	;	20/02/2017
  3111                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3112                              <1> 	;	
  3113                              <1> 	;	CF = 1 -> error 
  3114                              <1> 	;
  3115                              <1> 	; Modified Registers -> EBP (except EAX)
  3116                              <1> 	;
  3117 00003024 E8ABFDFFFF          <1> 	call	allocate_page
  3118 00003029 725B                <1> 	jc	short dpt_err
  3119                              <1> 	;
  3120 0000302B 50                  <1> 	push	eax ; *
  3121 0000302C 56                  <1> 	push	esi
  3122 0000302D 57                  <1> 	push	edi
  3123 0000302E 52                  <1> 	push	edx
  3124 0000302F 51                  <1> 	push	ecx
  3125                              <1> 	;
  3126 00003030 89DE                <1> 	mov	esi, ebx
  3127 00003032 89C7                <1> 	mov	edi, eax
  3128 00003034 89C2                <1> 	mov	edx, eax
  3129 00003036 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3130                              <1> dpt_0:
  3131 0000303C AD                  <1> 	lodsd
  3132 0000303D 21C0                <1> 	and	eax, eax
  3133 0000303F 7435                <1> 	jz	short dpt_3
  3134 00003041 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3135                              <1> 	; 24/12/2021
  3136 00003043 7503                <1> 	jnz	short dpt_1
  3137                              <1> 	;jz	short dpt_p_err
  3138                              <1> 	; 31/12/2021
  3139 00003045 F9                  <1> 	stc
  3140 00003046 EB39                <1> 	jmp	short dpt_p_err
  3141                              <1> 
  3142                              <1> ; 24/12/2021
  3143                              <1> ; ('reload_page' procedure call is disabled)
  3144                              <1> ;
  3145                              <1> ;	; 20/07/2015
  3146                              <1> ;	; ebp = virtual (linear) address of the memory page
  3147                              <1> ;	call	reload_page ; 28/04/2015
  3148                              <1> ;	jc	short dpt_p_err
  3149                              <1> dpt_1:
  3150                              <1> 	; 21/09/2015
  3151 00003048 89C1                <1> 	mov	ecx, eax
  3152 0000304A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3153 0000304E F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3154 00003051 751A                <1> 	jnz	short dpt_2
  3155                              <1> 	; Read only (parent) page
  3156                              <1> 	; 	- there is a third process which uses this page -
  3157                              <1> 	; Allocate a new page for the child process
  3158 00003053 E87CFDFFFF          <1> 	call	allocate_page
  3159 00003058 7227                <1> 	jc	short dpt_p_err
  3160 0000305A 57                  <1> 	push	edi
  3161 0000305B 56                  <1> 	push	esi
  3162 0000305C 89CE                <1> 	mov	esi, ecx
  3163 0000305E 89C7                <1> 	mov	edi, eax
  3164 00003060 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3165 00003065 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3166 00003067 5E                  <1> 	pop	esi
  3167 00003068 5F                  <1> 	pop	edi
  3168                              <1> 	;
  3169                              <1> 
  3170                              <1> ; 24/12/2021
  3171                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3172                              <1> ; 
  3173                              <1> ;	push	ebx
  3174                              <1> ;	push	eax
  3175                              <1> ;	; 20/07/2015
  3176                              <1> ;	mov	ebx, ebp
  3177                              <1> ;	; ebx = virtual (linear) address of the memory page
  3178                              <1> ;	call	add_to_swap_queue
  3179                              <1> ;	pop	eax
  3180                              <1> ;	pop	ebx
  3181                              <1> 
  3182                              <1> 	; 21/09/2015
  3183 00003069 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3184                              <1> 		; user + writable + present page
  3185 0000306B EB09                <1> 	jmp	short dpt_3
  3186                              <1> dpt_2:
  3187                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3188 0000306D 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3189                              <1> 		    ; (read only page!)
  3190 0000306F 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3191 00003072 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3192                              <1> dpt_3:
  3193 00003076 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3194                              <1> 	;
  3195 00003077 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3196                              <1> 	;
  3197 0000307D 39D7                <1> 	cmp	edi, edx
  3198 0000307F 72BB                <1> 	jb	short dpt_0
  3199                              <1> dpt_p_err:
  3200 00003081 59                  <1> 	pop	ecx
  3201 00003082 5A                  <1> 	pop	edx
  3202 00003083 5F                  <1> 	pop	edi
  3203 00003084 5E                  <1> 	pop	esi
  3204 00003085 58                  <1> 	pop	eax ; *
  3205                              <1> dpt_err:
  3206 00003086 C3                  <1> 	retn
  3207                              <1> 
  3208                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3209                              <1> 	; 31/12/2021
  3210                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3211                              <1> 	; 21/09/2015
  3212                              <1> 	; 19/09/2015
  3213                              <1> 	; 17/09/2015
  3214                              <1> 	; 28/08/2015
  3215                              <1> 	; 20/07/2015
  3216                              <1> 	; 28/06/2015
  3217                              <1> 	; 03/05/2015
  3218                              <1> 	; 30/04/2015
  3219                              <1> 	; 18/04/2015
  3220                              <1> 	; 12/04/2015
  3221                              <1> 	; 30/10/2014
  3222                              <1> 	; 11/09/2014
  3223                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3224                              <1> 	;
  3225                              <1> 	; Note: This is not an interrupt/exception handler.
  3226                              <1> 	;	This is a 'page fault remedy' subroutine 
  3227                              <1> 	;	which will be called by standard/uniform
  3228                              <1> 	;	exception handler.
  3229                              <1> 	;
  3230                              <1> 	; INPUT -> 
  3231                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3232                              <1> 	;
  3233                              <1> 	;	cr2 = the virtual (linear) address 
  3234                              <1> 	;	      which has caused to page fault (19/09/2015)
  3235                              <1> 	;
  3236                              <1> 	; OUTPUT ->
  3237                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3238                              <1> 	;	EAX = 0 -> no error
  3239                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3240                              <1> 	;
  3241                              <1> 	; Modified Registers -> none (except EAX)
  3242                              <1> 	;	
  3243                              <1>         ;
  3244                              <1>         ; ERROR CODE:
  3245                              <1> 	;	 31  .....	4   3	2   1	0
  3246                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3247                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3248                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3249                              <1> 	;
  3250                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3251                              <1>     	;		a page-protection violation. When not set,
  3252                              <1> 	;		it was caused by a non-present page.
  3253                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3254                              <1> 	;		a page write. When not set, it was caused
  3255                              <1> 	;		by a page read.
  3256                              <1> 	; U : USER    -	When set, the page fault was caused 
  3257                              <1> 	;		while CPL = 3. 
  3258                              <1> 	;		This does not necessarily mean that
  3259                              <1> 	;		the page fault was a privilege violation.
  3260                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3261                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3262                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3263                              <1> 	;     FETCH	an instruction fetch
  3264                              <1> 	;
  3265                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3266                              <1> 	;  31               22                  12 11                    0
  3267                              <1> 	; +-------------------+-------------------+-----------------------+
  3268                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3269                              <1>        	; +-------------------+-------------------+-----------------------+
  3270                              <1> 	;
  3271                              <1> 
  3272                              <1> 	;; CR3 REGISTER (Control Register 3)
  3273                              <1> 	;  31                                   12             5 4 3 2   0
  3274                              <1> 	; +---------------------------------------+-------------+---+-----+
  3275                              <1>       	; |                                       |  		|P|P|     |
  3276                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3277                              <1>       	; |                                       | 		|D|T|     |
  3278                              <1>    	; +---------------------------------------+-------------+---+-----+
  3279                              <1> 	;
  3280                              <1> 	;	PWT    - WRITE THROUGH
  3281                              <1> 	;	PCD    - CACHE DISABLE		
  3282                              <1> 	;
  3283                              <1> 	;
  3284                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3285                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3286                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3287                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3288                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3289                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3290                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3291                              <1> 	;
  3292                              <1>         ;       P      - PRESENT
  3293                              <1>         ;       R/W    - READ/WRITE
  3294                              <1>         ;       U/S    - USER/SUPERVISOR
  3295                              <1> 	;	PWT    - WRITE THROUGH
  3296                              <1> 	;	PCD    - CACHE DISABLE	
  3297                              <1> 	;	A      - ACCESSED	
  3298                              <1>         ;       D      - DIRTY (IGNORED)
  3299                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3300                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3301                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3302                              <1> 	;
  3303                              <1> 	;
  3304                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3305                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3306                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3307                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3308                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3309                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3310                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3311                              <1> 	;
  3312                              <1>         ;       P      - PRESENT
  3313                              <1>         ;       R/W    - READ/WRITE
  3314                              <1>         ;       U/S    - USER/SUPERVISOR
  3315                              <1> 	;	PWT    - WRITE THROUGH
  3316                              <1> 	;	PCD    - CACHE DISABLE	
  3317                              <1> 	;	A      - ACCESSED	
  3318                              <1>         ;       D      - DIRTY
  3319                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3320                              <1> 	;	G      - GLOBAL	 
  3321                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3322                              <1> 	;
  3323                              <1> 	;
  3324                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3325                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3326                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3327                              <1>       	; |                                       |     | | | | | | |U|R| |
  3328                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3329                              <1>       	; |                                       |     | | | | | | |S|W| |
  3330                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3331                              <1> 	;
  3332                              <1>         ;       P      - PRESENT
  3333                              <1>         ;       R/W    - READ/WRITE
  3334                              <1>         ;       U/S    - USER/SUPERVISOR
  3335                              <1>         ;       D      - DIRTY
  3336                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3337                              <1> 	;
  3338                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3339                              <1> 	;
  3340                              <1> 	;
  3341                              <1> 	;; Invalid Page Table Entry
  3342                              <1> 	; 31                                                           1 0
  3343                              <1>       	; +-------------------------------------------------------------+-+
  3344                              <1>       	; |                                                             | |
  3345                              <1>       	; |                          AVAILABLE                          |0|
  3346                              <1>       	; |                                                             | |
  3347                              <1>       	; +-------------------------------------------------------------+-+
  3348                              <1> 	;
  3349                              <1> 
  3350 00003087 53                  <1> 	push	ebx
  3351 00003088 52                  <1> 	push	edx
  3352 00003089 51                  <1> 	push	ecx
  3353                              <1> 	;
  3354                              <1> 	; 21/09/2015 (debugging)
  3355 0000308A FF05[BF6F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3356 00003090 FF05[506C0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3357                              <1> 	; 28/06/2015
  3358                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3359 00003096 8A15[486C0000]      <1> 	mov	dl, [error_code]
  3360                              <1> 	;
  3361 0000309C F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3362                              <1> 			; sign
  3363 0000309F 7425                <1> 	jz	short pfh_alloc_np
  3364                              <1> 	; 
  3365                              <1> 	; If it is not a 'write on read only page' type page fault
  3366                              <1> 	; major page fault error with minor reason must be returned without 
  3367                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3368                              <1> 	; after return here!
  3369                              <1> 	; Page fault will be remedied, by copying page contents
  3370                              <1> 	; to newly allocated page with write permission;
  3371                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3372                              <1> 	; used for working with minimum possible memory usage. 
  3373                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3374                              <1> 	; process with 'read only' flag. If the child process attempts to
  3375                              <1> 	; write on these read only pages, page fault will be directed here
  3376                              <1> 	; for allocating a new page with same data/content. 
  3377                              <1> 	;
  3378                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3379                              <1> 	; will not force to separate CODE and DATA space 
  3380                              <1> 	; in a process/program... 
  3381                              <1> 	; CODE segment/section may contain DATA!
  3382                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3383                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3384                              <1> 	;	
  3385 000030A1 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3386                              <1> 			; sign
  3387 000030A4 7418                <1>         jz      pfh_p_err
  3388                              <1> 	; 31/08/2015
  3389 000030A6 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3390                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3391 000030A9 7413                <1>         jz	short pfh_pv_err
  3392                              <1> 	;
  3393                              <1> 	; make a new page and copy the parent's page content
  3394                              <1> 	; as the child's new page content
  3395                              <1> 	;
  3396 000030AB 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3397                              <1> 			 ; which has caused to page fault
  3398 000030AE E87C000000          <1> 	call 	copy_page
  3399 000030B3 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3400                              <1> 	;
  3401 000030B5 EB72                <1>         jmp     pfh_cpp_ok
  3402                              <1> 
  3403                              <1> 	; 31/12/2021 (short jump)
  3404                              <1> pfh_im_err:
  3405 000030B7 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3406                              <1> 			; Major (Primary) Error: Page Fault
  3407                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3408 000030BC EB6D                <1> 	jmp	short pfh_err_retn
  3409                              <1> 
  3410                              <1> 	; 31/12/2021
  3411                              <1> pfh_p_err: ; 09/03/2015
  3412                              <1> pfh_pv_err:
  3413                              <1> 	; Page fault was caused by a protection-violation
  3414 000030BE B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3415                              <1> 			; Major (Primary) Error: Page Fault
  3416                              <1> 			; Minor (Secondary) Error: Protection violation !
  3417 000030C3 F9                  <1> 	stc
  3418 000030C4 EB65                <1> 	jmp	short pfh_err_retn
  3419                              <1> 	
  3420                              <1> pfh_alloc_np:
  3421 000030C6 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3422 000030CB 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3423                              <1> pfh_chk_cpl:
  3424                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3425                              <1> 		; (Lower 12 bits are ZERO, because 
  3426                              <1> 		;	the address is on a page boundary)
  3427 000030CD 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3428 000030D0 7505                <1> 	jnz	short pfh_um
  3429                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3430 000030D2 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3431                              <1> 			 ; of the current/active page directory
  3432                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3433                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3434 000030D5 EB06                <1> 	jmp	short pfh_get_pde
  3435                              <1> 	;
  3436                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3437 000030D7 8B1D[AF6F0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3438                              <1> 			; Physical address of the USER's page directory
  3439                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3440                              <1> pfh_get_pde:
  3441 000030DD 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3442 000030E0 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3443                              <1> 			 ; which has been caused to page fault
  3444                              <1> 			 ;
  3445 000030E3 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3446 000030E6 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3447                              <1> 	;
  3448 000030E9 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3449 000030EB 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3450 000030ED F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3451 000030F0 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3452                              <1> 			  	  ; set/validate page directory entry
  3453 000030F2 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3454 000030F7 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3455 000030F9 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3456 000030FB EB16                <1> 	jmp	short pfh_get_pte
  3457                              <1> pfh_set_pde:
  3458                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3459                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3460                              <1> 	;
  3461 000030FD 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3462 000030FF 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3463 00003101 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3464 00003103 89C3                <1> 	mov	ebx, eax
  3465 00003105 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3466 0000310A 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3467                              <1> pfh_spde_1:
  3468                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3469 0000310C 89C1                <1> 	mov	ecx, eax
  3470 0000310E E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3471                              <1> pfh_get_pte:
  3472 00003113 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3473                              <1> 			 ; which has been caused to page fault
  3474 00003116 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3475 00003118 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3476                              <1> 			 ; higher 20 bits of the page fault address 
  3477 0000311B 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3478 00003120 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3479 00003123 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3480                              <1> ; 24/12/2021
  3481                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3482                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3483                              <1> ; 24/12/2021
  3484                              <1> ; ('swap_in' procedure call has been disabled)
  3485                              <1> ;
  3486                              <1> ;	and	eax, eax
  3487                              <1> ;	jz	short pfh_gpte_1
  3488                              <1> ;	; 20/07/2015
  3489                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3490                              <1> ;	push	ebp ; 20/07/2015
  3491                              <1> ;	mov	ebp, cr2
  3492                              <1> ;		; ECX = physical address of the page table entry
  3493                              <1> ;		; EBX = Memory page address (physical!)
  3494                              <1> ;		; EAX = Swap disk (offset) address
  3495                              <1> ;		; EBP = virtual address (page fault address)
  3496                              <1> ;	call	swap_in
  3497                              <1> ;	pop	ebp
  3498                              <1> ;	jc      short pfh_err_retn
  3499                              <1> ;	xchg	ecx, ebx
  3500                              <1> ;		; EBX = physical address of the page table entry
  3501                              <1> ;		; ECX = new page
  3502                              <1> pfh_gpte_1:
  3503 00003125 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3504 00003127 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3505                              <1> pfh_cpp_ok:
  3506                              <1> ; 24/12/2021
  3507                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3508                              <1> ;
  3509                              <1> ;	; 20/07/2015
  3510                              <1> ;	mov	ebx, cr2
  3511                              <1> ;	call 	add_to_swap_queue
  3512                              <1> 	;
  3513                              <1> 	; The new PTE (which contains the new page) will be added to 
  3514                              <1> 	; the swap queue, here. 
  3515                              <1> 	; (Later, if memory will become insufficient, 
  3516                              <1> 	; one page will be swapped out which is at the head of 
  3517                              <1> 	; the swap queue by using FIFO and access check methods.)
  3518                              <1> 	;
  3519 00003129 31C0                <1> 	xor	eax, eax  ; 0
  3520                              <1> 	;
  3521                              <1> pfh_err_retn:
  3522 0000312B 59                  <1> 	pop	ecx
  3523 0000312C 5A                  <1> 	pop	edx
  3524 0000312D 5B                  <1> 	pop	ebx
  3525 0000312E C3                  <1> 	retn 
  3526                              <1> 	
  3527                              <1> copy_page:
  3528                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3529                              <1> 	; 16/04/2021
  3530                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3531                              <1> 	; 22/09/2015
  3532                              <1> 	; 21/09/2015
  3533                              <1> 	; 19/09/2015
  3534                              <1> 	; 07/09/2015
  3535                              <1> 	; 31/08/2015
  3536                              <1> 	; 20/07/2015
  3537                              <1> 	; 05/05/2015
  3538                              <1> 	; 03/05/2015
  3539                              <1> 	; 18/04/2015
  3540                              <1> 	; 12/04/2015
  3541                              <1> 	; 30/10/2014
  3542                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3543                              <1> 	;
  3544                              <1> 	; INPUT -> 
  3545                              <1> 	;	EBX = Virtual (linear) address of source page
  3546                              <1> 	;	     (Page fault address)
  3547                              <1> 	; OUTPUT ->
  3548                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3549                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3550                              <1> 	;	EAX = 0 (CF = 1) 
  3551                              <1> 	;		if there is not a free page to be allocated
  3552                              <1> 	;	(page content of the source page will be copied
  3553                              <1> 	;	onto the target/new page) 	
  3554                              <1> 	;
  3555                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3556                              <1> 	;
  3557                              <1> 
  3558                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3559                              <1> 	; INPUT: 
  3560                              <1> 	;	EBX = Virtual (linear) address of source page
  3561                              <1> 	;	     (Page fault address)
  3562                              <1> 	; OUTPUT:
  3563                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3564                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3565                              <1> 	;	EAX = 0 (CF = 1) 
  3566                              <1> 	;		if there is not a free page to be allocated
  3567                              <1> 	;	(page content of the source page will be copied
  3568                              <1> 	;	onto the target/new page) 	
  3569                              <1> 	;
  3570                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3571                              <1> 	
  3572 0000312F 56                  <1> 	push	esi ; *
  3573 00003130 57                  <1> 	push	edi ; **
  3574                              <1> 	; 16/04/2021
  3575                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3576                              <1> 	;push	ebx ; ***
  3577                              <1> 	;push	ecx ; ****
  3578 00003131 31F6                <1> 	xor 	esi, esi
  3579 00003133 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3580 00003136 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3581 00003138 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3582 0000313B 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3583 0000313E 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3584 00003140 031D[AF6F0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3585 00003146 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3586 00003148 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3587 0000314C 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3588 0000314E 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3589 00003154 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3590 00003158 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3591                              <1> 	; 07/09/2015
  3592 0000315A 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3593                              <1> 				     ; read only page as a child process?)	
  3594 0000315F 7509                <1> 	jnz	short cpp_0 ; yes
  3595 00003161 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3596 00003163 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3597 00003168 EB32                <1> 	jmp	short cpp_1
  3598                              <1> cpp_0:
  3599 0000316A 89FE                <1> 	mov	esi, edi
  3600 0000316C 0335[B36F0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3601 00003172 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3602 00003174 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3603 00003178 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3604 0000317A 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3605 00003180 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3606 00003184 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3607 00003186 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3608                              <1> 	; 21/09/2015
  3609 00003188 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3610 0000318A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3611                              <1> 	;
  3612 0000318E F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3613 00003191 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3614                              <1> 	;
  3615 00003193 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3616 00003198 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3617 0000319A 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3618                              <1> 			    ; Convert child's page to writable page
  3619                              <1> cpp_1:
  3620 0000319C E833FCFFFF          <1> 	call	allocate_page
  3621 000031A1 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3622 000031A3 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3623 000031A5 7405                <1> 	jz	short cpp_2
  3624                              <1> 		; Convert read only page to writable page 
  3625                              <1> 		;(for the parent of the current process)
  3626                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3627                              <1> 	; 22/09/2015
  3628 000031A7 890E                <1> 	mov	[esi], ecx
  3629 000031A9 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3630                              <1> 				 ; 1+2+4 = 7
  3631                              <1> cpp_2:
  3632 000031AC 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3633                              <1> 	; 07/09/2015
  3634 000031AE 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3635 000031B0 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3636 000031B5 F3A5                <1> 	rep	movsd ; 31/08/2015
  3637                              <1> cpp_3:		
  3638 000031B7 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3639 000031B9 8903                <1> 	mov	[ebx], eax ; Update PTE
  3640 000031BB 28C0                <1> 	sub	al, al ; clear attributes
  3641                              <1> cpp_4:
  3642                              <1> 	; 16/04/2021
  3643                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3644                              <1> 	;pop	ecx ; ****
  3645                              <1> 	;pop	ebx ; ***
  3646 000031BD 5F                  <1> 	pop	edi ; **
  3647 000031BE 5E                  <1> 	pop	esi ; *
  3648 000031BF C3                  <1> 	retn
  3649                              <1> 
  3650                              <1> ;; 28/04/2015
  3651                              <1> ;; 24/10/2014
  3652                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3653                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3654                              <1> ;;
  3655                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3656                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3657                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3658                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3659                              <1> ;;
  3660                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3661                              <1> ;;
  3662                              <1> ;; Method:
  3663                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3664                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3665                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3666                              <1> ;;	When a new page is being allocated, swap queue is updated
  3667                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3668                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3669                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3670                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3671                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3672                              <1> ;;	offset value becomes it's previous offset value - 4.
  3673                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3674                              <1> ;;	the queue/list is not shifted.
  3675                              <1> ;;	After the queue/list shift, newly allocated page is added
  3676                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3677                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3678                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3679                              <1> ;;	
  3680                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3681                              <1> ;;	the first non-accessed, writable page in the list, 
  3682                              <1> ;;	from the head to the tail. The list is shifted to left 
  3683                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3684                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3685                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3686                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3687                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3688                              <1> ;;	procedure will be failed)...
  3689                              <1> ;;
  3690                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3691                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3692                              <1> ;;	(PTE) will be added to the tail of the queue after
  3693                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3694                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3695                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3696                              <1> ;;
  3697                              <1> ;;
  3698                              <1> ;;	
  3699                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3700                              <1> ;;
  3701                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3702                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3703                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3704                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3705                              <1> ;;
  3706                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3707                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3708                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3709                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3710                              <1> ;; 		 (entire swap space must be accessed by using
  3711                              <1> ;;		 31 bit offset address) 
  3712                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3713                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3714                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3715                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3716                              <1> ;;
  3717                              <1> ;; 					
  3718                              <1> ;; Method:
  3719                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3720                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3721                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3722                              <1> ;;	Swapping out is performed by using swap page queue.
  3723                              <1> ;;
  3724                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3725                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3726                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3727                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3728                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3729                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3730                              <1> ;;	calculated by adding offset value to the swap partition's 
  3731                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3732                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3733                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3734                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3735                              <1> ;;	is in a partitioned virtual hard disk.) 
  3736                              <1> ;;
  3737                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3738                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3739                              <1> ;;
  3740                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3741                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3742                              <1> ;;
  3743                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3744                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3745                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3746                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3747                              <1> ;;	it means relevant (respective) block is in use, and, 
  3748                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3749                              <1> ;;      swap disk/file block is free.
  3750                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3751                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3752                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3753                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3754                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3755                              <1> ;;	------------------------------------------------------------
  3756                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3757                              <1> ;;	------------------------------------------------------------
  3758                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3759                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3760                              <1> ;;
  3761                              <1> ;;	..............................................................
  3762                              <1> ;;
  3763                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3764                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3765                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3766                              <1> ;;	position with value of 1 on the table is converted to swap
  3767                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3768                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3769                              <1> ;;	number of physical swap disk or virtual swap disk)
  3770                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3771                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3772                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3773                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3774                              <1> ;;	If disk write procedure returns with error or free count of 
  3775                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3776                              <1> ;;	'insufficient memory error' (cf=1). 
  3777                              <1> ;;
  3778                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3779                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3780                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3781                              <1> ;;	free blocks after a disk write error. It will return to 
  3782                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3783                              <1> ;;
  3784                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3785                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3786                              <1> ;;	address (cf=0). 
  3787                              <1> ;;
  3788                              <1> ;;	..............................................................
  3789                              <1> ;;
  3790                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3791                              <1> ;;	file sectors at specified memory page. Then page allocation
  3792                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3793                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3794                              <1> ;;	to do, except to terminate the process which is the owner of
  3795                              <1> ;;	the swapped page.
  3796                              <1> ;;
  3797                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3798                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3799                              <1> ;;	updates [swpd_first] pointer if it is required.
  3800                              <1> ;;
  3801                              <1> ;;	..............................................................	 
  3802                              <1> ;;
  3803                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3804                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3805                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3806                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3807                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3808                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3809                              <1> ;;
  3810                              <1> 
  3811                              <1> ; 24/12/2021
  3812                              <1> ; ('swap_in' procedure call is disabled)
  3813                              <1> 
  3814                              <1> ;swap_in:
  3815                              <1> 	; 31/08/2015
  3816                              <1> 	; 20/07/2015
  3817                              <1> 	; 28/04/2015
  3818                              <1> 	; 18/04/2015
  3819                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3820                              <1> 	;
  3821                              <1> 	; INPUT -> 
  3822                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3823                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3824                              <1> 	;	EAX = Offset Address for the swapped page on the
  3825                              <1> 	;	      swap disk or in the swap file.
  3826                              <1> 	;
  3827                              <1> 	; OUTPUT ->
  3828                              <1> 	;	EAX = 0 if loading at memory has been successful
  3829                              <1> 	;
  3830                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3831                              <1> 	;		  or sector not present or drive not ready
  3832                              <1> 	;	     EAX = Error code
  3833                              <1> 	;	     [u.error] = EAX 
  3834                              <1> 	;		       = The last error code for the process
  3835                              <1> 	;		         (will be reset after returning to user)	  
  3836                              <1> 	;
  3837                              <1> 	; Modified Registers -> EAX
  3838                              <1> 	;
  3839                              <1> 
  3840                              <1> ;       cmp     dword [swp_drv], 0
  3841                              <1> ;	jna	short swpin_dnp_err
  3842                              <1> ;
  3843                              <1> ;	cmp	eax, [swpd_size]
  3844                              <1> ;	jnb	short swpin_snp_err
  3845                              <1> ;
  3846                              <1> ;	push	esi
  3847                              <1> ;	push	ebx
  3848                              <1> ;	push	ecx
  3849                              <1> ;	mov	esi, [swp_drv]	
  3850                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3851                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3852                              <1> ;		; size different than 512 bytes, logical disk sector
  3853                              <1> ;		; size is 512 bytes and disk reading procedure
  3854                              <1> ;		; will be performed for reading 4096 bytes
  3855                              <1> ;		; (2*2048, 8*512). 
  3856                              <1> ;	; ESI = Logical disk description table address
  3857                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3858                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3859                              <1> ;	; ECX = Sector count ; 8 sectors
  3860                              <1> ;	push	eax
  3861                              <1> ;	call	logical_disk_read
  3862                              <1> ;	pop	eax
  3863                              <1> ;	jnc	short swpin_read_ok
  3864                              <1> ;	;
  3865                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3866                              <1> ;	mov	[u.error], eax
  3867                              <1> ;	jmp	short swpin_retn
  3868                              <1> ;	;
  3869                              <1> ;swpin_read_ok:
  3870                              <1> ;	; EAX = Offset address (logical sector number)
  3871                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3872                              <1> ;	;
  3873                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3874                              <1> ;	; 20/07/2015
  3875                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3876                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3877                              <1> ;	mov	bl, [u.uno] ; current process number
  3878                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3879                              <1> ;	call	swap_queue_shift
  3880                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3881                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3882                              <1> ;	; zf = 1
  3883                              <1> ;swpin_retn:
  3884                              <1> ;	pop	ecx
  3885                              <1> ;	pop	ebx
  3886                              <1> ;	pop	esi
  3887                              <1> ;	retn
  3888                              <1> ;
  3889                              <1> ;swpin_dnp_err:
  3890                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3891                              <1> ;swpin_err_retn:
  3892                              <1> ;	mov	[u.error], eax
  3893                              <1> ;	stc
  3894                              <1> ;	retn
  3895                              <1> ;
  3896                              <1> ;swpin_snp_err:
  3897                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3898                              <1> ;	jmp	short swpin_err_retn
  3899                              <1> 
  3900                              <1> ; 24/12/2021
  3901                              <1> ; ('swap_out' procedure call is disabled)
  3902                              <1> 
  3903                              <1> ;swap_out:
  3904                              <1> 	; 10/06/2016
  3905                              <1> 	; 07/06/2016
  3906                              <1>         ; 23/05/2016
  3907                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3908                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3909                              <1> 	;
  3910                              <1> 	; INPUT -> 
  3911                              <1> 	;	none
  3912                              <1> 	;
  3913                              <1> 	; OUTPUT ->
  3914                              <1> 	;	EAX = Physical page address (which is swapped out
  3915                              <1> 	;	      for allocating a new page)
  3916                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3917                              <1> 	;		  or sector not present or drive not ready
  3918                              <1> 	;	     EAX = Error code
  3919                              <1> 	;	     [u.error] = EAX 
  3920                              <1> 	;		       = The last error code for the process
  3921                              <1> 	;		         (will be reset after returning to user)	  
  3922                              <1> 	;
  3923                              <1> 	; Modified Registers -> none (except EAX)
  3924                              <1> 	;
  3925                              <1> 
  3926                              <1> ;	cmp 	word [swpq_count], 1
  3927                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3928                              <1> ;
  3929                              <1> ;       ;cmp    dword [swp_drv], 1
  3930                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3931                              <1> ;
  3932                              <1> ;       cmp     dword [swpd_free], 1
  3933                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3934                              <1> ;
  3935                              <1> ;	push	ebx ; *
  3936                              <1> ;swpout_1:
  3937                              <1> ;	; 10/06/2016
  3938                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3939                              <1> ;	call	swap_queue_shift
  3940                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3941                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3942                              <1> ;				       ; pointer in the swap queue
  3943                              <1> ;	; EAX = PTE value of the page
  3944                              <1> ;	; EBX = PTE address of the page
  3945                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3946                              <1> ;	;
  3947                              <1> ;	; 07/06/2016
  3948                              <1> ;	; 19/05/2016
  3949                              <1> ;	; check this page is in timer events or not
  3950                              <1> ;	
  3951                              <1> ;swpout_timer_page_0:
  3952                              <1> ;	push	edx ; **
  3953                              <1> ;
  3954                              <1> ;	; 07/06/2016
  3955                              <1> ;	cmp	byte [timer_events], 0 
  3956                              <1> ;	jna	short swpout_2
  3957                              <1> ;	;
  3958                              <1> ;	mov	dl, [timer_events]
  3959                              <1> ;
  3960                              <1> ;	push	ecx ; ***
  3961                              <1> ;	push	ebx ; ****
  3962                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3963                              <1> ;			       ; structures 
  3964                              <1> ;swpout_timer_page_1:
  3965                              <1> ;	mov	cl, [ebx]
  3966                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3967                              <1> ;	jz	short swpout_timer_page_3
  3968                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3969                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3970                              <1> ;				; of the response byte address, to
  3971                              <1> ;				; get beginning of the page address)
  3972                              <1> ;	cmp	eax, ecx
  3973                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3974                              <1> ;	
  3975                              <1> ;	; !same page!
  3976                              <1> ;	;
  3977                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3978                              <1> ;	; This page will be used by the kernel to put timer event
  3979                              <1> ;	; response (signal return) byte at the requested address;
  3980                              <1> ;	; in order to prevent a possible wrong write (while
  3981                              <1> ;	; this page is swapped out) on physical memory,
  3982                              <1> ;	; we must protect this page against to be swapped out!
  3983                              <1> ;	;
  3984                              <1> ;	pop	ebx ; ****
  3985                              <1> ;	pop	ecx ; ***
  3986                              <1> ;	pop	edx ; **
  3987                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3988                              <1> ; 
  3989                              <1> ;swpout_timer_page_2:
  3990                              <1> ;	; 07/06/2016
  3991                              <1> ;	dec	dl
  3992                              <1> ;	jz	short swpout_timer_page_4
  3993                              <1> ;swpout_timer_page_3:
  3994                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3995                              <1> ;	;jnb	short swpout_timer_page_4
  3996                              <1> ;	add	ebx, 16
  3997                              <1> ;	jmp	short swpout_timer_page_1	
  3998                              <1> ;
  3999                              <1> ;swpout_timer_page_4:
  4000                              <1> ;	pop	ebx ; ****
  4001                              <1> ;	pop	ecx ; ***
  4002                              <1> ;swpout_2:
  4003                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4004                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4005                              <1> ;	;
  4006                              <1> ;	call	link_swap_block
  4007                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4008                              <1> ;				       ; because [swpd_free] value
  4009                              <1> ;				       ; was checked at the beginging. 	
  4010                              <1> ;	pop	edx ; **
  4011                              <1> ;	pop	ebx ; *
  4012                              <1> ;	jmp	short swpout_nfspc_err 
  4013                              <1> ;swpout_3:
  4014                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4015                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4016                              <1> ;	;	
  4017                              <1> ;	push	esi ; **
  4018                              <1> ;	push	ecx ; ***
  4019                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4020                              <1> ;	mov	esi, [swp_drv]	
  4021                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4022                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4023                              <1> ;		; size different than 512 bytes, logical disk sector
  4024                              <1> ;		; size is 512 bytes and disk writing procedure
  4025                              <1> ;		; will be performed for writing 4096 bytes
  4026                              <1> ;		; (2*2048, 8*512). 
  4027                              <1> ;	; ESI = Logical disk description table address
  4028                              <1> ;	; EBX = Buffer (Page) address
  4029                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4030                              <1> ;	; ECX = Sector count ; 8 sectors
  4031                              <1> ;	; edx = PTE address
  4032                              <1> ;	call	logical_disk_write
  4033                              <1> ;	; edx = PTE address
  4034                              <1> ;	pop	ecx ; sector address	
  4035                              <1> ;	jnc	short swpout_write_ok
  4036                              <1> ;	;
  4037                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4038                              <1> ;swpout_dw_err:
  4039                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4040                              <1> ;	mov	[u.error], eax
  4041                              <1> ;	jmp	short swpout_retn
  4042                              <1> ;	;
  4043                              <1> ;swpout_write_ok:
  4044                              <1> ;	; EBX = Buffer (page) address
  4045                              <1> ;	; EDX = Page Table Entry address
  4046                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4047                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4048                              <1> ;	mov 	[edx], ecx 
  4049                              <1> ;		; bit 0 = 0 (swapped page)
  4050                              <1> ;	mov	eax, ebx
  4051                              <1> ;swpout_retn:
  4052                              <1> ;	pop	ecx ; ***
  4053                              <1> ;	pop	esi ; **
  4054                              <1> ;	pop	ebx ; *
  4055                              <1> ;	retn
  4056                              <1> ;
  4057                              <1> ;;swpout_dnp_err:
  4058                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4059                              <1> ;;	jmp	short swpout_err_retn
  4060                              <1> ;swpout_nfspc_err:
  4061                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4062                              <1> ;swpout_err_retn:
  4063                              <1> ;	mov	[u.error], eax
  4064                              <1> ;	;stc
  4065                              <1> ;	retn
  4066                              <1> ;swpout_npts_err:
  4067                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4068                              <1> ;	pop	ebx
  4069                              <1> ;	jmp	short swpout_err_retn
  4070                              <1> ;swpout_im_err:
  4071                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4072                              <1> ;	jmp	short swpout_err_retn
  4073                              <1> 
  4074                              <1> ; 24/12/2021
  4075                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4076                              <1> 
  4077                              <1> ;swap_queue_shift:
  4078                              <1> 	; 26/03/2017
  4079                              <1> 	; 10/06/2016
  4080                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4081                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4082                              <1> 	;
  4083                              <1> 	; INPUT ->
  4084                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4085                              <1> 	;	      and process number combination (bit 0 to 11)
  4086                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4087                              <1> 	;	
  4088                              <1> 	; OUTPUT ->
  4089                              <1> 	;	If EBX input > 0 
  4090                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4091                              <1> 	; 	   from the tail to the head, up to entry offset
  4092                              <1> 	; 	   which points to EBX input value or nothing
  4093                              <1> 	;	   to do if EBX value is not found on the queue.
  4094                              <1> 	;	   (The entry -with EBX value- will be removed
  4095                              <1> 	;	   from the queue if it is found.)
  4096                              <1> 	;
  4097                              <1> 	;	   EAX = 0		
  4098                              <1> 	;
  4099                              <1> 	;	If EBX input = 0
  4100                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4101                              <1> 	; 	   from the tail to the head, if the PTE address
  4102                              <1> 	;	   which is pointed in head of the queue is marked
  4103                              <1> 	;	   as "accessed" or it is marked as "non present".
  4104                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4105                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4106                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4107                              <1> 	;	   -without dropping pointer of the PTE from 
  4108                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4109                              <1> 	;	   Pointer in the head will be moved into the tail,
  4110                              <1> 	;	   other PTEs will be shifted on head direction.)
  4111                              <1> 	;
  4112                              <1> 	;	   Swap queue will be shifted up to the first
  4113                              <1> 	;	   'present' or 'non accessed' page will be found
  4114                              <1> 	;	   (as pointed) on the queue head (then it will be
  4115                              <1>         ;          removed/dropped from the queue).
  4116                              <1> 	;
  4117                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4118                              <1> 	;		 (it's pointer -virtual address-) dropped
  4119                              <1> 	;		 (removed) from swap queue.
  4120                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4121                              <1> 	;	         which is (it's pointer -virtual address-)
  4122                              <1> 	;		 dropped (removed) from swap queue.
  4123                              <1> 	;
  4124                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4125                              <1> 	;
  4126                              <1> 	; Modified Registers -> EAX, EBX
  4127                              <1> 	;
  4128                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4129                              <1> ;	and	ax, ax
  4130                              <1> ;	jz	short swpqs_retn
  4131                              <1> ;	push	edi
  4132                              <1> ;	push	esi
  4133                              <1> ;	push	ecx
  4134                              <1> ;	mov	esi, swap_queue
  4135                              <1> ;	mov	ecx, eax
  4136                              <1> ;	or	ebx, ebx
  4137                              <1> ;	jz	short swpqs_7
  4138                              <1> ;swpqs_1:
  4139                              <1> ;	lodsd
  4140                              <1> ;	cmp	eax, ebx
  4141                              <1> ;	je	short swpqs_2
  4142                              <1> ;	loop	swpqs_1
  4143                              <1> ;	; 10/06/2016
  4144                              <1> ;	sub	eax, eax 
  4145                              <1> ;	jmp	short swpqs_6
  4146                              <1> ;swpqs_2:
  4147                              <1> ;	mov	edi, esi
  4148                              <1> ;	sub 	edi, 4
  4149                              <1> ;swpqs_3:
  4150                              <1> ;	dec	word [swpq_count]
  4151                              <1> ;	jz	short swpqs_5
  4152                              <1> ;swpqs_4:
  4153                              <1> ;	dec 	ecx
  4154                              <1> ;	rep	movsd	; shift up (to the head)
  4155                              <1> ;swpqs_5:
  4156                              <1> ;	xor	eax, eax
  4157                              <1> ;	mov	[edi], eax
  4158                              <1> ;swpqs_6:
  4159                              <1> ;	pop	ecx
  4160                              <1> ;	pop	esi
  4161                              <1> ;	pop	edi
  4162                              <1> ;swpqs_retn:
  4163                              <1> ;	retn		
  4164                              <1> ;swpqs_7:
  4165                              <1> ;	mov	edi, esi ; head
  4166                              <1> ;	lodsd
  4167                              <1> ;	; 20/07/2015
  4168                              <1> ;	mov	ebx, eax
  4169                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4170                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4171                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4172                              <1> ;		      ; ax = process number (1 to 4095)
  4173                              <1> ;	cmp	al, [u.uno]
  4174                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4175                              <1> ;	jne	short swpqs_8
  4176                              <1> ;	mov	eax, [u.pgdir]
  4177                              <1> ;	jmp	short swpqs_9
  4178                              <1> ;swpqs_8:
  4179                              <1> ;	; 09/06/2016
  4180                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4181                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4182                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4183                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4184                              <1> ;
  4185                              <1> ;	;shl	ax, 2
  4186                              <1> ;	shl	al, 2
  4187                              <1> ;	mov 	eax, [eax+p.upage-4]
  4188                              <1> ;	or	eax, eax
  4189                              <1> ;	jz	short swpqs_3 ; invalid upage
  4190                              <1> ;	add	eax, u.pgdir - user
  4191                              <1> ;			 ; u.pgdir value for the process
  4192                              <1> ;			 ; is in [eax]
  4193                              <1> ;	mov	eax, [eax]
  4194                              <1> ;	and	eax, eax
  4195                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4196                              <1> ;swpqs_9:
  4197                              <1> ;	push	edx
  4198                              <1> ;	; eax = page directory
  4199                              <1> ;	; ebx = virtual address
  4200                              <1> ;	call	get_pte
  4201                              <1> ;	mov	ebx, edx	; PTE address
  4202                              <1> ;	pop	edx
  4203                              <1> ;	; 10/06/2016
  4204                              <1> ;	jc	short swpqs_13 ; empty PDE
  4205                              <1> ;	; EAX = PTE value
  4206                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4207                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4208                              <1> ;			        ; from the queue (head)
  4209                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4210                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4211                              <1> ;			        ; from the queue (head) 	
  4212                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4213                              <1> ;	;jnz	short swpqs_11  ; present
  4214                              <1> ;			        ; accessed page
  4215                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4216                              <1> ;	jc	short swpqs_11  ; accessed page
  4217                              <1> ;
  4218                              <1> ;	dec	ecx
  4219                              <1> ;	mov	[swpq_count], cx
  4220                              <1> ;       jz      short swpqs_10
  4221                              <1> ;		; esi = head + 4
  4222                              <1> ;		; edi = head
  4223                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4224                              <1> ;swpqs_10:
  4225                              <1> ;	mov	[edi], ecx ; 0
  4226                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4227                              <1> ;
  4228                              <1> ;swpqs_11:
  4229                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4230                              <1> ;	; Rotation (head -> tail)
  4231                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4232                              <1> ;	jz	short swpqs_10
  4233                              <1> ;		; esi = head + 4
  4234                              <1> ;		; edi = head
  4235                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4236                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4237                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4238                              <1> ;
  4239                              <1> ;	mov	cx, [swpq_count]
  4240                              <1> ;
  4241                              <1> ;swpqs_12:
  4242                              <1> ;	mov	esi, swap_queue ; head
  4243                              <1> ;       jmp     swpqs_7
  4244                              <1> ;
  4245                              <1> ;swpqs_13:
  4246                              <1> ;	dec	ecx
  4247                              <1> ;	mov	[swpq_count], cx
  4248                              <1> ;       jz      swpqs_5
  4249                              <1> ;	jmp	short swpqs_12
  4250                              <1> 
  4251                              <1> ; 24/12/2021
  4252                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4253                              <1> 
  4254                              <1> ;add_to_swap_queue:
  4255                              <1> 	; 20/02/2017
  4256                              <1> 	; 20/07/2015
  4257                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4258                              <1> 	;
  4259                              <1> 	; Adds new page to swap queue
  4260                              <1> 	; (page directories and page tables must not be added
  4261                              <1> 	; to swap queue)	
  4262                              <1> 	;
  4263                              <1> 	; INPUT ->
  4264                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4265                              <1> 	;	[u.uno]
  4266                              <1> 	;	20/02/2017
  4267                              <1> 	;	(Linear address = CORE + user's virtual address)
  4268                              <1> 	;
  4269                              <1> 	; OUTPUT ->
  4270                              <1> 	;	EAX = [swpq_count]
  4271                              <1> 	;	      (after the PTE has been added)
  4272                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4273                              <1> 	;	      the PTE could not be added.
  4274                              <1> 	;
  4275                              <1> 	; Modified Registers -> EAX
  4276                              <1> 	;
  4277                              <1> ;	push	ebx
  4278                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4279                              <1> ;	mov	bl, [u.uno] ; current process number
  4280                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4281                              <1> ;				 ; it is already on the queue
  4282                              <1> ;		; then add it to the tail of the queue
  4283                              <1> ;	movzx	eax, word [swpq_count]
  4284                              <1> ;	cmp	ax, 1024
  4285                              <1> ;	jb	short atsq_1
  4286                              <1> ;	sub	ax, ax
  4287                              <1> ;	pop	ebx
  4288                              <1> ;	retn
  4289                              <1> ;atsq_1:
  4290                              <1> ;	push	esi
  4291                              <1> ;	mov	esi, swap_queue
  4292                              <1> ;	and	ax, ax
  4293                              <1> ;	jz	short atsq_2
  4294                              <1> ;	shl	ax, 2	; convert to offset
  4295                              <1> ;	add	esi, eax
  4296                              <1> ;	shr	ax, 2
  4297                              <1> ;atsq_2:
  4298                              <1> ;	inc	ax
  4299                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4300                              <1> ;	mov	[swpq_count], ax
  4301                              <1> ;	pop	esi
  4302                              <1> ;	pop	ebx
  4303                              <1> ;	retn
  4304                              <1> 
  4305                              <1> ; 24/12/2021
  4306                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4307                              <1> 
  4308                              <1> ;unlink_swap_block:
  4309                              <1> 	; 15/09/2015
  4310                              <1> 	; 30/04/2015
  4311                              <1> 	; 18/04/2015
  4312                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4313                              <1> 	;
  4314                              <1> 	; INPUT -> 
  4315                              <1> 	;	EAX = swap disk/file offset address
  4316                              <1> 	;	      (bit 1 to bit 31)
  4317                              <1> 	; OUTPUT ->
  4318                              <1> 	;	[swpd_free] is increased
  4319                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4320                              <1> 	;
  4321                              <1> 	; Modified Registers -> EAX
  4322                              <1> 	;
  4323                              <1> ;	push	ebx
  4324                              <1> ;	push	edx
  4325                              <1> ;	;
  4326                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4327                              <1> ;				     ; 3 bits right
  4328                              <1> ;				     ; to get swap block/page number
  4329                              <1> ;	mov	edx, eax
  4330                              <1> ;	; 15/09/2015
  4331                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4332                              <1> ;				     ; (1 allocation bit = 1 page)
  4333                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4334                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4335                              <1> ;				     ; (to get 32 bit position)			
  4336                              <1> ;	;
  4337                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4338                              <1> ;	add	ebx, edx
  4339                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4340                              <1> ;				     ; (allocation bit position)	 
  4341                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4342                              <1> ;				     ; than the address in 'swpd_next' ?
  4343                              <1> ;				     ; (next/first free block value)		
  4344                              <1> ;	jnb	short uswpbl_1	     ; no	
  4345                              <1> ;	mov	[swpd_next], eax     ; yes	
  4346                              <1> ;uswpbl_1:
  4347                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4348                              <1> ;				     ; set relevant bit to 1.
  4349                              <1> ;				     ; set CF to the previous bit value	
  4350                              <1> ;	cmc			     ; complement carry flag	
  4351                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4352                              <1> ;				     ; if the block is already deallocated
  4353                              <1> ;				     ; before.	
  4354                              <1> ;       inc     dword [swpd_free]
  4355                              <1> ;uswpbl_2:
  4356                              <1> ;	pop	edx
  4357                              <1> ;	pop	ebx
  4358                              <1> ;	retn
  4359                              <1> 
  4360                              <1> ; 24/12/2021
  4361                              <1> ; ('link_swap_block' procedure call is disabled)
  4362                              <1> 
  4363                              <1> ;link_swap_block:
  4364                              <1> 	; 01/07/2015
  4365                              <1> 	; 18/04/2015
  4366                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4367                              <1> 	;
  4368                              <1> 	; INPUT -> none
  4369                              <1> 	;
  4370                              <1> 	; OUTPUT ->
  4371                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4372                              <1> 	;	      in sectors (corresponding 
  4373                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4374                              <1> 	;
  4375                              <1> 	;	CF = 1 and EAX = 0 
  4376                              <1> 	; 		   if there is not a free block to be allocated	
  4377                              <1> 	;
  4378                              <1> 	; Modified Registers -> none (except EAX)
  4379                              <1> 	;
  4380                              <1> 
  4381                              <1> ;	;mov	eax, [swpd_free]
  4382                              <1> ;	;and	eax, eax
  4383                              <1> ;	;jz	short out_of_swpspc
  4384                              <1> ;	;
  4385                              <1> ;	push	ebx
  4386                              <1> ;	push	ecx
  4387                              <1> ;	;
  4388                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4389                              <1> ;	mov	ecx, ebx
  4390                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4391                              <1> ;				 ; next_free_swap_block >> 5
  4392                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4393                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4394                              <1> ;lswbl_scan:
  4395                              <1> ;	cmp	ebx, ecx
  4396                              <1> ;	ja	short lswbl_notfound
  4397                              <1> ;	;
  4398                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4399                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4400                              <1> ;			   ; loads the destination with an index to
  4401                              <1> ;			   ; first set bit. (0 -> 31) 
  4402                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4403                              <1> ;	; 01/07/2015
  4404                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4405                              <1> ;			 ;
  4406                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4407                              <1> ;			 ;	  with value of 1 means 
  4408                              <1> ;			 ;	  the corresponding page is free 
  4409                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4410                              <1> ;	add	ebx, 4
  4411                              <1> ;			 ; We return back for searching next page block
  4412                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4413                              <1> ;			 ;	 we always will find at least 1 free block here.
  4414                              <1> ;	jmp    	short lswbl_scan
  4415                              <1> ;	;
  4416                              <1> ;lswbl_notfound:	
  4417                              <1> ;	sub	ecx, swap_alloc_table
  4418                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4419                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4420                              <1> ;	xor	eax, eax
  4421                              <1> ;	mov	[swpd_free], eax
  4422                              <1> ;	stc
  4423                              <1> ;lswbl_ok:
  4424                              <1> ;	pop	ecx
  4425                              <1> ;	pop	ebx
  4426                              <1> ;	retn
  4427                              <1> ;	;
  4428                              <1> ;;out_of_swpspc:
  4429                              <1> ;;	stc
  4430                              <1> ;;	retn
  4431                              <1> ;
  4432                              <1> ;lswbl_found:
  4433                              <1> ;	mov	ecx, ebx
  4434                              <1> ;	sub	ecx, swap_alloc_table
  4435                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4436                              <1> ;				 ; address/offset (to the next)
  4437                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4438                              <1> ;	;
  4439                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4440                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4441                              <1> ;				 ; in the destination.
  4442                              <1> ;				 ;
  4443                              <1> ;				 ; Reset the bit which is corresponding to the 
  4444                              <1> ;				 ; (just) allocated block.
  4445                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4446                              <1> ;	add	eax, ecx	 ; = block number
  4447                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4448                              <1> ;				 ; 1 block =  8 sectors
  4449                              <1> ;	;
  4450                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4451                              <1> ;	;
  4452                              <1> ;	; NOTE: The relevant page table entry will be updated
  4453                              <1> ;	;       according to this EAX value...
  4454                              <1> ;	;
  4455                              <1> ;	jmp	short lswbl_ok
  4456                              <1> 
  4457                              <1> ; 24/12/2021
  4458                              <1> ; ('logical_disk_read' procedure call is disabled)
  4459                              <1> 
  4460                              <1> ;logical_disk_read:
  4461                              <1> 	; 20/07/2015
  4462                              <1> 	; 09/03/2015 (temporary code here)
  4463                              <1> 	;
  4464                              <1> 	; INPUT ->
  4465                              <1> 	; 	ESI = Logical disk description table address
  4466                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4467                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4468                              <1> 	; 	ECX = Sector count
  4469                              <1> 	;
  4470                              <1> 	;
  4471                              <1> ;	retn
  4472                              <1> 
  4473                              <1> ; 24/12/2021
  4474                              <1> ; ('logical_disk_write' procedure call is disabled)
  4475                              <1> 
  4476                              <1> ;logical_disk_write:
  4477                              <1> 	; 20/07/2015
  4478                              <1> 	; 09/03/2015 (temporary code here)
  4479                              <1> 	;
  4480                              <1> 	; INPUT ->
  4481                              <1> 	; 	ESI = Logical disk description table address
  4482                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4483                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4484                              <1> 	; 	ECX = Sector count
  4485                              <1> 	;
  4486                              <1> ;	retn
  4487                              <1> 
  4488                              <1> get_physical_addr:
  4489                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4490                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4491                              <1> 	; 18/10/2015
  4492                              <1> 	; 29/07/2015
  4493                              <1> 	; 20/07/2015
  4494                              <1> 	; 04/06/2015
  4495                              <1> 	; 20/05/2015
  4496                              <1> 	; 28/04/2015
  4497                              <1> 	; 18/04/2015
  4498                              <1> 	; Get physical address
  4499                              <1> 	;     (allocates a new page for user if it is not present)
  4500                              <1> 	;	
  4501                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4502                              <1> 	; (buffer) address to physical address (of the buffer).)
  4503                              <1> 	; ('sys write', 'sys read' system calls...)
  4504                              <1> 	;
  4505                              <1> 	; INPUT ->
  4506                              <1> 	;	EBX = virtual address
  4507                              <1> 	;	u.pgdir = page directory (physical) address
  4508                              <1> 	;
  4509                              <1> 	; OUTPUT ->
  4510                              <1> 	;	EAX = physical address 
  4511                              <1> 	;	EBX = linear address	
  4512                              <1> 	;	EDX = physical address of the page frame
  4513                              <1> 	;	      (with attribute bits)
  4514                              <1> 	;	ECX = byte count within the page frame
  4515                              <1> 	;
  4516                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4517                              <1> 	;
  4518                              <1> 
  4519                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4520 000031C0 A1[AF6F0000]        <1> 	mov	eax, [u.pgdir]
  4521                              <1> 
  4522                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4523                              <1> 	
  4524 000031C5 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4525                              <1> 	;
  4526                              <1> 	;mov	eax, [u.pgdir]
  4527 000031CB E816FDFFFF          <1> 	call	get_pte
  4528                              <1> 		; EDX = Page table entry address (if CF=0)
  4529                              <1> 	        ;       Page directory entry address (if CF=1)
  4530                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4531                              <1> 		; EAX = Page table entry value (page address)
  4532                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4533 000031D0 731C                <1> 	jnc	short gpa_1
  4534                              <1> 	;
  4535 000031D2 E8FDFBFFFF          <1> 	call	allocate_page
  4536 000031D7 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4537                              <1> gpa_0:
  4538 000031D9 E867FCFFFF          <1> 	call 	clear_page
  4539                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4540 000031DE 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4541                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4542                              <1> 			   ; (user, writable, present page)	
  4543 000031E0 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4544 000031E2 A1[AF6F0000]        <1> 	mov	eax, [u.pgdir]	
  4545 000031E7 E8FAFCFFFF          <1> 	call	get_pte
  4546 000031EC 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4547                              <1> gpa_1:
  4548                              <1> 	; EAX = PTE value, EDX = PTE address
  4549 000031EE A801                <1> 	test 	al, PTE_A_PRESENT
  4550 000031F0 750A                <1> 	jnz	short gpa_3
  4551 000031F2 09C0                <1> 	or	eax, eax
  4552 000031F4 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4553                              <1> 
  4554                              <1> ; 24/12/2021
  4555                              <1> ; ('reload_page' procedure call is disabled)
  4556 000031F6 EB2C                <1> 	jmp	short gpa_im_err
  4557                              <1> 
  4558                              <1> 	; 20/07/2015
  4559                              <1> ;	push	ebp
  4560                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4561                              <1> ;	; reload swapped page
  4562                              <1> ;	call	reload_page ; 28/04/2015
  4563                              <1> ;	pop	ebp
  4564                              <1> ;	jc	short gpa_retn
  4565                              <1> gpa_2:
  4566                              <1> ; 24/12/2021
  4567                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4568                              <1> 
  4569                              <1> 	; 20/07/2015
  4570                              <1> 	; 20/05/2015
  4571                              <1> 	; add this page to swap queue
  4572                              <1> ;	push	eax 
  4573                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4574                              <1> ;	call 	add_to_swap_queue
  4575                              <1> ;	pop	eax
  4576                              <1> 		; PTE address in EDX
  4577                              <1> 		; virtual address in EBX
  4578                              <1> 	; EAX = memory page address
  4579 000031F8 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4580                              <1> 				  ; present flag, bit 0 = 1
  4581                              <1> 				  ; user flag, bit 2 = 1	
  4582                              <1> 				  ; writable flag, bit 1 = 1
  4583 000031FA 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4584                              <1> gpa_3:
  4585                              <1> 	; 18/10/2015
  4586 000031FC 89D9                <1> 	mov	ecx, ebx
  4587 000031FE 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4588 00003204 89C2                <1> 	mov 	edx, eax
  4589 00003206 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4590 0000320A 01C8                <1> 	add	eax, ecx
  4591 0000320C F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4592 0000320E 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4593 00003214 F8                  <1> 	clc
  4594                              <1> gpa_retn:
  4595 00003215 C3                  <1> 	retn	
  4596                              <1> gpa_4:	
  4597 00003216 E8B9FBFFFF          <1> 	call	allocate_page
  4598 0000321B 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4599 0000321D E823FCFFFF          <1> 	call	clear_page
  4600 00003222 EBD4                <1> 	jmp	short gpa_2
  4601                              <1> 
  4602                              <1> gpa_im_err:	
  4603 00003224 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4604                              <1> 				  ; Major error = 0 (No protection fault)	
  4605 00003229 C3                  <1> 	retn
  4606                              <1> 
  4607                              <1> ; 24/12/2021
  4608                              <1> ; ('reload_page' procedure call is disabled)
  4609                              <1> 
  4610                              <1> ;reload_page:
  4611                              <1> 	; 20/07/2015
  4612                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4613                              <1> 	;
  4614                              <1> 	; Reload (Restore) swapped page at memory
  4615                              <1> 	;
  4616                              <1> 	; INPUT -> 
  4617                              <1> 	;	EBP = Virtual (linear) memory address
  4618                              <1> 	;	EAX = PTE value (swap disk sector address)
  4619                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4620                              <1> 	; OUTPUT ->
  4621                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4622                              <1> 	;
  4623                              <1> 	;	CF = 1 and EAX = error code
  4624                              <1> 	;
  4625                              <1> 	; Modified Registers -> none (except EAX)
  4626                              <1> 	;
  4627                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4628                              <1> ;	push	ebx      ;
  4629                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4630                              <1> ;	call	allocate_page
  4631                              <1> ;	jc	short rlp_im_err
  4632                              <1> ;	xchg 	eax, ebx	
  4633                              <1> ;	; EBX = Physical memory (page) address
  4634                              <1> ;	; EAX = Swap disk (offset) address
  4635                              <1> ;	; EBP = Virtual (linear) memory address
  4636                              <1> ;	call	swap_in
  4637                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4638                              <1> ;	mov	eax, ebx	
  4639                              <1> ;rlp_retn:
  4640                              <1> ;	pop	ebx
  4641                              <1> ;	retn
  4642                              <1> ;	
  4643                              <1> ;rlp_im_err:	
  4644                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4645                              <1> ;				  ; Major error = 0 (No protection fault)	
  4646                              <1> ;	jmp	short rlp_retn
  4647                              <1> ;
  4648                              <1> ;rlp_swp_err:
  4649                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4650                              <1> ;	jmp	short rlp_retn
  4651                              <1> 
  4652                              <1> copy_page_dir:
  4653                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4654                              <1> 	; 19/09/2015
  4655                              <1> 	; temporary - 07/09/2015
  4656                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4657                              <1> 	;
  4658                              <1> 	; INPUT -> 
  4659                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4660                              <1> 	;		    page directory.
  4661                              <1> 	; OUTPUT ->
  4662                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4663                              <1> 	;	       page directory.
  4664                              <1> 	;	(New page directory with new page table entries.)
  4665                              <1> 	;	(New page tables with read only copies of the parent's
  4666                              <1> 	;	pages.)
  4667                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4668                              <1> 	;
  4669                              <1> 	; Modified Registers -> none (except EAX)
  4670                              <1> 	;
  4671 0000322A E8A5FBFFFF          <1> 	call	allocate_page
  4672 0000322F 723E                <1> 	jc	short cpd_err
  4673                              <1> 	;
  4674 00003231 55                  <1> 	push	ebp ; 20/07/2015
  4675 00003232 56                  <1> 	push	esi
  4676 00003233 57                  <1> 	push	edi
  4677 00003234 53                  <1> 	push	ebx
  4678 00003235 51                  <1> 	push	ecx
  4679 00003236 8B35[AF6F0000]      <1> 	mov	esi, [u.pgdir]
  4680 0000323C 89C7                <1> 	mov	edi, eax
  4681 0000323E 50                  <1> 	push	eax ; save child's page directory address
  4682                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4683                              <1> 	; (use same system space for all user page tables) 
  4684 0000323F A5                  <1> 	movsd
  4685 00003240 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4686 00003245 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4687                              <1> cpd_0:	
  4688 0000324A AD                  <1> 	lodsd
  4689                              <1> 	;or	eax, eax
  4690                              <1>         ;jnz	short cpd_1
  4691 0000324B A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4692 0000324D 7508                <1> 	jnz	short cpd_1
  4693                              <1>  	; (virtual address at the end of the page table)	
  4694 0000324F 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4695 00003255 EB0F                <1> 	jmp	short cpd_2
  4696                              <1> cpd_1:	
  4697 00003257 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4698 0000325B 89C3                <1> 	mov	ebx, eax
  4699                              <1> 	; EBX = Parent's page table address
  4700 0000325D E81F000000          <1> 	call	copy_page_table
  4701 00003262 720C                <1> 	jc	short cpd_p_err
  4702                              <1> 	; EAX = Child's page table address
  4703 00003264 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4704                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4705                              <1> 			 ; (present, writable, user)
  4706                              <1> cpd_2:
  4707 00003266 AB                  <1> 	stosd
  4708 00003267 E2E1                <1> 	loop	cpd_0
  4709                              <1> 	;
  4710 00003269 58                  <1> 	pop	eax  ; restore child's page directory address
  4711                              <1> cpd_3:
  4712 0000326A 59                  <1> 	pop	ecx
  4713 0000326B 5B                  <1> 	pop	ebx
  4714 0000326C 5F                  <1> 	pop	edi
  4715 0000326D 5E                  <1> 	pop	esi
  4716 0000326E 5D                  <1> 	pop	ebp
  4717                              <1> cpd_err:
  4718 0000326F C3                  <1> 	retn
  4719                              <1> cpd_p_err:
  4720                              <1> 	; release the allocated pages missing (recover free space)
  4721 00003270 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4722 00003271 8B1D[AF6F0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4723 00003277 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4724 0000327C 29C0                <1> 	sub	eax, eax ; 0
  4725 0000327E F9                  <1> 	stc
  4726 0000327F EBE9                <1> 	jmp	short cpd_3	
  4727                              <1> 
  4728                              <1> copy_page_table:
  4729                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4730                              <1> 	; 19/09/2015
  4731                              <1> 	; temporary - 07/09/2015
  4732                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4733                              <1> 	;
  4734                              <1> 	; INPUT -> 
  4735                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4736                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4737                              <1> 	; OUTPUT ->
  4738                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4739                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4740                              <1> 	;	CF = 1 -> error 
  4741                              <1> 	;
  4742                              <1> 	; Modified Registers -> EBP (except EAX)
  4743                              <1> 	;
  4744 00003281 E84EFBFFFF          <1> 	call	allocate_page
  4745 00003286 7244                <1> 	jc	short cpt_err
  4746                              <1> 	;
  4747 00003288 50                  <1> 	push	eax ; *
  4748                              <1> 	;push 	ebx
  4749 00003289 56                  <1> 	push	esi
  4750 0000328A 57                  <1> 	push	edi
  4751 0000328B 52                  <1> 	push	edx
  4752 0000328C 51                  <1> 	push	ecx
  4753                              <1> 	;
  4754 0000328D 89DE                <1> 	mov	esi, ebx
  4755 0000328F 89C7                <1> 	mov	edi, eax
  4756 00003291 89C2                <1> 	mov	edx, eax
  4757 00003293 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4758                              <1> cpt_0:
  4759 00003299 AD                  <1> 	lodsd
  4760 0000329A A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4761                              <1> 	;jnz	short cpt_1 (*)
  4762                              <1> 	; 24/12/2021
  4763                              <1> 	;and	eax, eax (*)
  4764 0000329C 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4765                              <1> 	
  4766                              <1> ; 24/12/2021
  4767                              <1> ; ('reload_page' procedure call is disabled)
  4768                              <1> ;
  4769                              <1> ;	; ebp = virtual (linear) address of the memory page
  4770                              <1> ;	call	reload_page ; 28/04/2015
  4771                              <1> ;	jc	short cpt_p_err
  4772                              <1> cpt_1:
  4773 0000329E 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4774 000032A2 89C1                <1> 	mov	ecx, eax
  4775                              <1> 	; Allocate a new page for the child process
  4776 000032A4 E82BFBFFFF          <1> 	call	allocate_page
  4777 000032A9 721C                <1> 	jc	short cpt_p_err
  4778 000032AB 57                  <1> 	push	edi
  4779 000032AC 56                  <1> 	push	esi
  4780 000032AD 89CE                <1> 	mov	esi, ecx
  4781 000032AF 89C7                <1> 	mov	edi, eax
  4782 000032B1 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4783 000032B6 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4784 000032B8 5E                  <1> 	pop	esi
  4785 000032B9 5F                  <1> 	pop	edi
  4786                              <1> 	; 
  4787                              <1> ; 24/12/2021
  4788                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4789                              <1> ;
  4790                              <1> ;	push	ebx
  4791                              <1> ;	push	eax
  4792                              <1> ;	mov	ebx, ebp
  4793                              <1> ;	; ebx = virtual address of the memory page
  4794                              <1> ;	call	add_to_swap_queue
  4795                              <1> ;	pop	eax
  4796                              <1> ;	pop	ebx
  4797                              <1> 	;
  4798                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4799 000032BA 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4800                              <1> cpt_2:
  4801 000032BC AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4802                              <1> 	;
  4803 000032BD 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4804                              <1> 	;
  4805 000032C3 39D7                <1> 	cmp	edi, edx
  4806 000032C5 72D2                <1> 	jb	short cpt_0
  4807                              <1> cpt_p_err:
  4808 000032C7 59                  <1> 	pop	ecx
  4809 000032C8 5A                  <1> 	pop	edx
  4810 000032C9 5F                  <1> 	pop	edi
  4811 000032CA 5E                  <1> 	pop	esi
  4812                              <1> 	;pop	ebx
  4813 000032CB 58                  <1> 	pop	eax ; *
  4814                              <1> cpt_err:
  4815 000032CC C3                  <1> 	retn
  4816                              <1> 
  4817                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4818                              <1> 
  4819                              <1> ;; Data:
  4820                              <1> 
  4821                              <1> ; 09/03/2015
  4822                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4823                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4824                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4825                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4826                              <1> ;swpd_next:  dd 0 ; next free page block
  4827                              <1> ;swpd_last:  dd 0 ; last swap page block
  2045                                  %include 'sysdefs.inc' ; 09/03/2015
  2046                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  2047                              <1> ; Last Modification: 12/02/2022
  2048                              <1> ;
  2049                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2050                              <1> ; (Modified from 
  2051                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2052                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2053                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2054                              <1> ; ----------------------------------------------------------------------------
  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> ; ****************************************************************************
  2062                              <1> 
  2063                              <1> nproc 	equ	16  ; number of processes
  2064                              <1> nfiles 	equ	50
  2065                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2066                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2067                              <1> 
  2068                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2069                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2070                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2071                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2072                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2073                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2074                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2075                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2076                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2077                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2078                              <1> 	; '/core' dump file size = 32768 bytes
  2079                              <1>  
  2080                              <1> ; 08/03/2014 
  2081                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2082                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2083                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2084                              <1> 
  2085                              <1> ; 30/08/2013
  2086                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2087                              <1> 
  2088                              <1> ; 05/02/2014
  2089                              <1> ; process status
  2090                              <1> ;SFREE 	equ 0
  2091                              <1> ;SRUN	equ 1
  2092                              <1> ;SWAIT	equ 2
  2093                              <1> ;SZOMB	equ 3
  2094                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2095                              <1> 
  2096                              <1> ; 09/03/2015
  2097                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2098                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2099                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2100                              <1> 
  2101                              <1> ; 17/09/2015
  2102                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2103                              <1> 
  2104                              <1> ; 21/09/2015 (36) 
  2105                              <1> ; 01/07/2015 (35)
  2106                              <1> ; 14/07/2013 (0-34)
  2107                              <1> ; UNIX v1 system calls
  2108                              <1> _rele 	equ 0
  2109                              <1> _exit 	equ 1
  2110                              <1> _fork 	equ 2
  2111                              <1> _read 	equ 3
  2112                              <1> _write	equ 4
  2113                              <1> _open	equ 5
  2114                              <1> _close 	equ 6
  2115                              <1> _wait 	equ 7
  2116                              <1> _creat 	equ 8
  2117                              <1> _link 	equ 9
  2118                              <1> _unlink	equ 10
  2119                              <1> _exec	equ 11
  2120                              <1> _chdir	equ 12
  2121                              <1> _time 	equ 13
  2122                              <1> _mkdir 	equ 14
  2123                              <1> _chmod	equ 15
  2124                              <1> _chown	equ 16
  2125                              <1> _break	equ 17
  2126                              <1> _stat	equ 18
  2127                              <1> _seek	equ 19
  2128                              <1> _tell 	equ 20
  2129                              <1> _mount	equ 21
  2130                              <1> _umount	equ 22
  2131                              <1> _setuid	equ 23
  2132                              <1> _getuid	equ 24
  2133                              <1> _stime	equ 25
  2134                              <1> _quit	equ 26	
  2135                              <1> _intr	equ 27
  2136                              <1> _fstat	equ 28
  2137                              <1> _emt 	equ 29
  2138                              <1> _mdate 	equ 30
  2139                              <1> _stty 	equ 31
  2140                              <1> _gtty	equ 32
  2141                              <1> _ilgins	equ 33
  2142                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2143                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2144                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2145                              <1> 
  2146                              <1> %macro sys 1-4
  2147                              <1>     ; 13/04/2015
  2148                              <1>     ; Retro UNIX 386 v1 system call.		
  2149                              <1>     mov eax, %1
  2150                              <1>     %if %0 >= 2   
  2151                              <1>         mov ebx, %2
  2152                              <1>         %if %0 >= 3    
  2153                              <1>             mov ecx, %3
  2154                              <1>             %if %0 = 4
  2155                              <1>                mov edx, %4   
  2156                              <1>             %endif
  2157                              <1>         %endif
  2158                              <1>     %endif
  2159                              <1>     int 30h	   
  2160                              <1> %endmacro
  2161                              <1> 
  2162                              <1> ; 13/05/2015 - ERROR CODES
  2163                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2164                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2165                              <1> ; 14/05/2015
  2166                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2167                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2168                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2169                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2170                              <1> ; 16/05/2015		
  2171                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2172                              <1> ; 18/05/2015
  2173                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2174                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2175                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2176                              <1> ; 07/06/2015
  2177                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2178                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2179                              <1> ; 09/06/2015
  2180                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2181                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2182                              <1> ; 16/06/2015
  2183                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2184                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2185                              <1> ; 22/06/2015
  2186                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2187                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2188                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2189                              <1> ; 23/06/2015
  2190                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2191                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2192                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2193                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2194                              <1> ; 27/06/2015
  2195                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2196                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2197                              <1> ; 29/06/2015
  2198                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2199                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2200                              <1> ; 12/02/2022 
  2201                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2202                              <1> ; 10/10/2016
  2203                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2204                              <1> ; 18/05/2016
  2205                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2206                              <1> ; 15/10/2016
  2207                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2208                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2209                              <1> ; 16/10/2016
  2210                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2211                              <1> ; 08/02/2022
  2212                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error	
  2213                              <1> 
  2214                              <1> ; 26/08/2015
  2215                              <1> ; 24/07/2015
  2216                              <1> ; 24/06/2015
  2217                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2218                              <1> ; 01/07/2015
  2219                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2220                              <1> ;	 					 		
  2046                                  %include 'u0.s'        ; 15/03/2015
  2047                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS0.INC
  2048                              <1> ; Last Modification: 02/06/2022
  2049                              <1> ; ----------------------------------------------------------------------------
  2050                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2051                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2052                              <1> ;
  2053                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2054                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2055                              <1> ; <Bell Laboratories (17/3/1972)>
  2056                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2057                              <1> ;
  2058                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2059                              <1> ;
  2060                              <1> ; ****************************************************************************
  2061                              <1> ; 21/11/2015
  2062                              <1> 
  2063                              <1> sys_init:
  2064                              <1> 	; 27/02/2022
  2065                              <1> 	; 23/02/2022
  2066                              <1> 	; 04/02/2022
  2067                              <1> 	; 18/10/2015
  2068                              <1> 	; 28/08/2015
  2069                              <1> 	; 24/08/2015
  2070                              <1> 	; 14/08/2015
  2071                              <1> 	; 24/07/2015 
  2072                              <1> 	; 02/07/2015
  2073                              <1> 	; 01/07/2015
  2074                              <1> 	; 23/06/2015
  2075                              <1> 	; 15/04/2015
  2076                              <1> 	; 13/04/2015
  2077                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2078                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2079                              <1> 	;
  2080                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2081                              <1> 	;
  2082                              <1> 	; 14/02/2014
  2083                              <1> 	; 14/07/2013
  2084                              <1> 	;;mov	ax, 41
  2085                              <1> 	; 27/02/2022
  2086                              <1> 	;xor	eax, eax
  2087                              <1> 	;mov	al, 41
  2088                              <1> 	;mov	[rootdir], ax
  2089                              <1> 	;mov	[u.cdir], ax
  2090                              <1> 	;;and	al, 1 ; 15/04/2015
  2091                              <1> 	;inc	al  ; ax = 1
  2092 000032CD B001                <1> 	mov	al, 1
  2093 000032CF A2[A56F0000]        <1> 	mov	[u.uno], al
  2094                              <1> 	;mov	[mpid], ax
  2095                              <1> 	;mov	[p.pid], ax
  2096 000032D4 A2[4A6F0000]        <1> 	mov	[mpid], al
  2097 000032D9 A2[786C0000]        <1> 	mov	[p.pid], al	
  2098 000032DE A2[D86C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2099                              <1> 	; 27/02/2022
  2100 000032E3 B029                <1> 	mov	al, 41
  2101                              <1> 	;mov	[rootdir], ax
  2102                              <1> 	;mov	[u.cdir], ax
  2103 000032E5 A2[4C6F0000]        <1> 	mov	[rootdir], al
  2104 000032EA A2[606F0000]        <1> 	mov	[u.cdir], al
  2105                              <1> 	;
  2106                              <1> 	; 23/02/2022
  2107                              <1>  	;call	epoch
  2108                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2109                              <1> 	; 17/07/2013
  2110 000032EF E88B060000          <1> 	call 	bf_init ; buffer initialization
  2111                              <1> 	; 23/02/2022
  2112                              <1> 	; (save sysinit time on sb0)
  2113 000032F4 E830030000          <1> 	call	epoch
  2114 000032F9 A3[A07D0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2115                              <1> 	; 23/06/2015
  2116 000032FE E8D1FAFFFF          <1> 	call	allocate_page
  2117                              <1> 	;;jc	error
  2118                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2119                              <1> 	; 04/02/2022
  2120 00003303 7305                <1> 	jnc	short sysinit_1
  2121 00003305 E990000000          <1> 	jmp	panic
  2122                              <1> sysinit_1:
  2123 0000330A A3[A66F0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2124 0000330F A3[E86C0000]        <1> 	mov	[p.upage], eax
  2125                              <1> 	;
  2126 00003314 E82CFBFFFF          <1> 	call	clear_page
  2127                              <1> 	;
  2128                              <1> 	; 14/08/2015
  2129 00003319 FA                  <1> 	cli
  2130                              <1> 	; 14/03/2015
  2131                              <1> 	; 17/01/2014
  2132 0000331A E8D7010000          <1> 	call	sp_init ; serial port initialization
  2133                              <1> 	; 14/08/2015
  2134 0000331F FB                  <1> 	sti
  2135                              <1> 	;
  2136                              <1> 	; 30/06/2015
  2137                              <1> 	;mov	esi, kernel_init_ok_msg
  2138                              <1> 	;call 	print_msg
  2139                              <1> 	;
  2140 00003320 30DB                <1> 	xor	bl, bl ; video page 0
  2141                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2142 00003322 E8400F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2143 00003327 FEC3                <1> 	inc	bl
  2144 00003329 80FB08              <1> 	cmp	bl, 8
  2145 0000332C 72F4                <1> 	jb	short vp_clr_nxt
  2146                              <1> 	;
  2147                              <1> 	; 24/07/2015
  2148                              <1> 	;push	KDATA
  2149                              <1>         ;push	esp
  2150                              <1> 	;mov	[tss.esp0], esp
  2151                              <1>         ;mov	word [tss.ss0], KDATA
  2152                              <1> 	;
  2153                              <1> 	; 27/02/2022
  2154                              <1> 	; 24/08/2015
  2155                              <1> 	;; temporary (01/07/2015)
  2156                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2157                              <1> 			       ; it is not needed here !
  2158                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2159 0000332E FE0D[536F0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2160                              <1> 			      ; 0 = executing a system call
  2161                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2162                              <1> 	;
  2163                              <1> 	;;; 06/08/2015
  2164                              <1> 	;;;call	getch ; wait for a key stroke
  2165                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2166                              <1> ;;sys_init_msg_wait:
  2167                              <1> ;;	push 	ecx
  2168                              <1> ;;	mov	al, 1
  2169                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2170                              <1> ;;	call	getc_n
  2171                              <1> ;;	pop	ecx
  2172                              <1> ;;	jnz	short sys_init_msg_ok
  2173                              <1> ;;	loop	sys_init_msg_wait
  2174                              <1> 	;
  2175                              <1> ;;sys_init_msg_ok:
  2176                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2177 00003334 6A10                <1> 	push	KDATA ; ss
  2178 00003336 54                  <1> 	push	esp
  2179 00003337 9C                  <1> 	pushfd
  2180 00003338 6A08                <1> 	push	KCODE ; cs
  2181 0000333A 68[6E330000]        <1> 	push	init_exec ; eip
  2182 0000333F 8925[546F0000]      <1> 	mov	[u.sp], esp
  2183 00003345 1E                  <1> 	push	ds
  2184 00003346 06                  <1> 	push	es
  2185 00003347 0FA0                <1> 	push	fs
  2186 00003349 0FA8                <1> 	push	gs	
  2187 0000334B 60                  <1> 	pushad
  2188 0000334C 8925[586F0000]      <1> 	mov	[u.usp], esp
  2189 00003352 E8B11B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2190                              <1> 		      ; and interrupt return components (for IRET)
  2191 00003357 61                  <1> 	popad
  2192 00003358 6658                <1> 	pop	ax ; gs
  2193 0000335A 6658                <1> 	pop	ax ; fs
  2194 0000335C 6658                <1> 	pop	ax ; es
  2195 0000335E 6658                <1> 	pop	ax ; ds	
  2196 00003360 58                  <1> 	pop	eax ; eip (init_exec)
  2197 00003361 6658                <1> 	pop	ax ; cs (KCODE)
  2198 00003363 58                  <1> 	pop	eax ; E-FLAGS
  2199 00003364 58                  <1> 	pop	eax ; esp
  2200 00003365 6658                <1> 	pop	ax ; ss (KDATA)
  2201                              <1> 	;
  2202 00003367 31C0                <1> 	xor	eax, eax ; 0
  2203 00003369 A3[B36F0000]        <1> 	mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2204                              <1> 	;
  2205                              <1> 	; 02/07/2015
  2206                              <1> 	; [u.pgdir ] = [k_page_dir]
  2207                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2208                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2209                              <1> init_exec:
  2210                              <1> 	; 13/03/2013
  2211                              <1> 	; 24/07/2013
  2212 0000336E BB[90330000]        <1> 	mov	ebx, init_file
  2213 00003373 B9[88330000]        <1> 	mov	ecx, init_argp
  2214                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2215                              <1> 	; ECX contains address of argument list pointer
  2216                              <1> 	;
  2217                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2218                              <1> 			      ; 0 = executing a system call
  2219                              <1> 	sys	_exec  ; execute file
  2147                              <2> 
  2148                              <2> 
  2149 00003378 B80B000000          <2>  mov eax, %1
  2150                              <2>  %if %0 >= 2
  2151                              <2>  mov ebx, %2
  2152                              <2>  %if %0 >= 3
  2153                              <2>  mov ecx, %3
  2154                              <2>  %if %0 = 4
  2155                              <2>  mov edx, %4
  2156                              <2>  %endif
  2157                              <2>  %endif
  2158                              <2>  %endif
  2159 0000337D CD30                <2>  int 30h
  2220 0000337F 7319                <1> 	jnc	short panic
  2221                              <1> 	;
  2222 00003381 BE[AA680000]        <1> 	mov	esi, etc_init_err_msg
  2223                              <1> 	; 27/02/2022
  2224                              <1> 	;call 	print_msg
  2225 00003386 EB17                <1> 	jmp	short key_to_reboot
  2226                              <1> 
  2227                              <1> ;align 4
  2228                              <1> init_argp:
  2229 00003388 [90330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2230                              <1> init_file:
  2231                              <1> 	; 24/08/2015
  2232 00003390 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2232 00003399 00                  <1>
  2233                              <1> panic:
  2234                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2235                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2236 0000339A BE[8F680000]        <1> 	mov 	esi, panic_msg
  2237                              <1> key_to_reboot: ; 27/02/2022
  2238 0000339F E819000000          <1> 	call 	print_msg
  2239                              <1> ;key_to_reboot:
  2240                              <1> 	; 15/11/2015
  2241 000033A4 E87C2C0000          <1> 	call 	getch 
  2242                              <1> 		; wait for a character from the current tty
  2243                              <1> 	;
  2244 000033A9 B00A                <1> 	mov	al, 0Ah
  2245 000033AB 8A1D[C66B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2246 000033B1 B407                <1> 	mov	ah, 07h ; Black background, 
  2247                              <1> 			; light gray forecolor
  2248 000033B3 E826E0FFFF          <1> 	call 	write_tty
  2249 000033B8 E9C1DCFFFF          <1> 	jmp	cpu_reset 
  2250                              <1> 
  2251                              <1> print_msg:
  2252                              <1> 	; 01/07/2015
  2253                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2254                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2255                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2256                              <1> 	;
  2257                              <1> 	;
  2258 000033BD AC                  <1> 	lodsb
  2259                              <1> pmsg1:
  2260 000033BE 56                  <1> 	push 	esi
  2261 000033BF 0FB61D[C66B0000]    <1> 	movzx	ebx, byte [ptty]
  2262 000033C6 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2263 000033C8 E811E0FFFF          <1> 	call 	write_tty
  2264 000033CD 5E                  <1> 	pop	esi
  2265 000033CE AC                  <1> 	lodsb
  2266 000033CF 20C0                <1> 	and 	al, al
  2267 000033D1 75EB                <1> 	jnz 	short pmsg1
  2268 000033D3 C3                  <1> 	retn
  2269                              <1> 	
  2270                              <1> ctrlbrk:
  2271                              <1> 	; 04/02/2022
  2272                              <1> 	; 01/02/2022
  2273                              <1> 	; 12/11/2015
  2274                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2275                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2276                              <1> 	;
  2277                              <1> 	; INT 1Bh (control+break) handler
  2278                              <1> 	;
  2279                              <1>       	; Retro Unix 8086 v1 feature only!
  2280                              <1>       	;
  2281 000033D4 66833D[9A6F0000]00  <1> 	cmp 	word [u.intr], 0
  2282 000033DC 764B                <1> 	jna 	short cbrk4
  2283                              <1> cbrk0:
  2284                              <1> 	; 12/11/2015
  2285                              <1> 	; 06/12/2013
  2286 000033DE 66833D[9C6F0000]00  <1> 	cmp 	word [u.quit], 0
  2287 000033E6 7441                <1> 	jz	short cbrk4
  2288                              <1> 	;
  2289                              <1> 	; 20/09/2013	
  2290                              <1> 	;push 	ax
  2291                              <1> 	; 01/02/2022
  2292 000033E8 50                  <1> 	push	eax
  2293                              <1> 
  2294                              <1> 	; 04/02/2022
  2295                              <1> 	; (repetitive ctrl+brk check) 
  2296 000033E9 66A1[9C6F0000]      <1> 	mov	ax, [u.quit]
  2297 000033EF 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2298 000033F1 7435                <1> 	jz	short cbrk3
  2299                              <1> 
  2300                              <1> 	; 20/09/2013
  2301 000033F3 A0[C66B0000]        <1> 	mov	al, [ptty]
  2302                              <1> 	;
  2303                              <1> 	; 12/11/2015
  2304                              <1> 	;
  2305                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2306                              <1> 	; or ctrl+break from console (pseudo) tty
  2307                              <1> 	; (!redirection!)
  2308                              <1> 	;
  2309 000033F8 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2310 000033FA 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2311                              <1> 	;	
  2312                              <1> 	; Serial port interrupt handler sets [ptty]
  2313                              <1> 	; to the port's tty number (as temporary).
  2314                              <1> 	;
  2315                              <1> 	; If active process is using a stdin or 
  2316                              <1> 	; stdout redirection (by the shell),
  2317                              <1>         ; console tty keyboard must be available
  2318                              <1> 	; to terminate running process,
  2319                              <1> 	; in order to prevent a deadlock. 
  2320                              <1> 	;
  2321 000033FC 52                  <1> 	push	edx
  2322 000033FD 0FB615[A56F0000]    <1> 	movzx	edx, byte [u.uno]
  2323 00003404 3A82[B76C0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2324 0000340A 5A                  <1> 	pop	edx
  2325 0000340B 7412                <1> 	je	short cbrk2
  2326                              <1> cbrk1:
  2327 0000340D FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2328                              <1> 	; 06/12/2013
  2329 0000340F 3A05[8C6F0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2330 00003415 7408                <1> 	je	short cbrk2	
  2331 00003417 3A05[8D6F0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2332 0000341D 7509                <1> 	jne	short cbrk3	
  2333                              <1> cbrk2:
  2334                              <1> 	;; 06/12/2013
  2335                              <1> 	;mov	ax, [u.quit]
  2336                              <1> 	;and	ax, ax
  2337                              <1> 	;jz	short cbrk3
  2338                              <1> 	;
  2339                              <1> 	;xor	ax, ax ; 0
  2340                              <1> 	;dec	ax
  2341                              <1> 	; 01/02/2022
  2342 0000341F 31C0                <1> 	xor	eax, eax ; 0
  2343 00003421 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2344                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2345 00003422 66A3[9C6F0000]      <1> 	mov	[u.quit], ax
  2346                              <1> cbrk3:
  2347                              <1> 	;pop	ax
  2348                              <1> 	; 01/02/2022
  2349 00003428 58                  <1> 	pop	eax
  2350                              <1> cbrk4:
  2351 00003429 C3                  <1> 	retn
  2352                              <1> 
  2353                              <1> com2_int:
  2354                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2355                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2356                              <1> 	; 07/11/2015 
  2357                              <1> 	; 24/10/2015
  2358                              <1> 	; 23/10/2015
  2359                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2360                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2361                              <1> 	; < serial port 2 interrupt handler >
  2362                              <1> 	;
  2363 0000342A 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2364                              <1> 	;;push	eax
  2365                              <1> 	; 08/01/2022
  2366 0000342D 29C0                <1> 	sub	eax, eax
  2367 0000342F B009                <1> 	mov	al, 9
  2368                              <1> 	;mov	ax, 9
  2369 00003431 EB07                <1> 	jmp	short comm_int
  2370                              <1> com1_int:
  2371                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2372                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2373                              <1> 	; 07/11/2015
  2374                              <1> 	; 24/10/2015
  2375 00003433 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2376                              <1> 	; 23/10/2015
  2377                              <1> 	;push	eax
  2378                              <1> 	; 08/01/2022
  2379 00003436 29C0                <1> 	sub	eax, eax
  2380 00003438 B008                <1> 	mov	al, 8
  2381                              <1> 	;mov	ax, 8
  2382                              <1> comm_int:
  2383                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2384                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2385                              <1> 	; 20/11/2015
  2386                              <1> 	; 18/11/2015
  2387                              <1> 	; 17/11/2015
  2388                              <1> 	; 16/11/2015
  2389                              <1> 	; 09/11/2015
  2390                              <1> 	; 08/11/2015
  2391                              <1> 	; 07/11/2015
  2392                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2393                              <1> 	; 01/11/2015
  2394                              <1> 	; 26/10/2015
  2395                              <1> 	; 23/10/2015
  2396 0000343A 53                  <1> 	push	ebx
  2397 0000343B 56                  <1> 	push	esi
  2398 0000343C 57                  <1> 	push	edi
  2399 0000343D 1E                  <1> 	push 	ds
  2400 0000343E 06                  <1> 	push 	es
  2401                              <1> 	; 18/11/2015
  2402 0000343F 0F20DB              <1> 	mov	ebx, cr3
  2403 00003442 53                  <1> 	push	ebx ; ****
  2404                              <1> 	;
  2405 00003443 51                  <1> 	push	ecx ; ***
  2406 00003444 52                  <1> 	push	edx ; **
  2407                              <1> 	;
  2408 00003445 BB10000000          <1> 	mov	ebx, KDATA
  2409 0000344A 8EDB                <1> 	mov	ds, bx
  2410 0000344C 8EC3                <1> 	mov	es, bx
  2411                              <1> 	;
  2412 0000344E 8B0D[986B0000]      <1> 	mov	ecx, [k_page_dir]
  2413 00003454 0F22D9              <1> 	mov	cr3, ecx
  2414                              <1> 	; 20/11/2015
  2415                              <1> 	; Interrupt identification register
  2416 00003457 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2417                              <1> 	;
  2418 0000345B 3C08                <1> 	cmp 	al, 8 
  2419 0000345D 7702                <1> 	ja 	short com_i0
  2420                              <1> 	;
  2421                              <1> 	; 04/02/2022 (Retro UNIX 386 v1)
  2422                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2423                              <1> 	; 20/11/2015
  2424                              <1> 	; 17/11/2015
  2425                              <1> 	; 16/11/2015
  2426                              <1> 	; 15/11/2015
  2427                              <1> 	; 24/10/2015
  2428                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2429                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2430                              <1> 	; < serial port 1 interrupt handler >
  2431                              <1> 	;
  2432 0000345F FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2433                              <1> com_i0:
  2434                              <1> 	;push	eax ; *
  2435                              <1> 	; 07/11/2015
  2436 00003461 A2[066C0000]        <1> 	mov 	byte [ccomport], al
  2437                              <1> 	; 09/11/2015
  2438                              <1> 	;movzx	ebx, ax ; 8 or 9
  2439                              <1> 	; 08/01/2022
  2440 00003466 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2441                              <1> 	; 17/11/2015
  2442                              <1>  	; reset request for response status
  2443 00003468 88A3[FC6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2444                              <1> 	;
  2445                              <1> 	; 20/11/2015
  2446 0000346E EC                  <1> 	in	al, dx		; read interrupt id. register
  2447 0000346F EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2448 00003471 2404                <1> 	and	al, 4		; received data available?	
  2449 00003473 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2450                              <1> 	;
  2451                              <1> 	; 20/11/2015
  2452 00003475 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2453 00003478 EC                  <1> 	in	al, dx     	; read character
  2454                              <1> 	;JMP	$+2	   	; I/O DELAY
  2455                              <1> 	; 08/11/2015
  2456                              <1> 	; 07/11/2015
  2457 00003479 89DE                <1> 	mov	esi, ebx 
  2458 0000347B 89DF                <1> 	mov	edi, ebx
  2459 0000347D 81C6[006C0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2460 00003483 81C7[026C0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2461 00003489 8806                <1> 	mov	[esi], al ; received char (current char)
  2462                              <1> 	; query
  2463 0000348B 20C0                <1> 	and	al, al
  2464 0000348D 7527                <1> 	jnz	short com_i2
  2465                              <1>    	; response
  2466                              <1> 	; 17/11/2015
  2467                              <1> 	; set request for response status
  2468 0000348F FE83[FC6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2469                              <1> 	;
  2470 00003495 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2471 00003499 EC                  <1> 	in	al, dx	   	; read line status register 
  2472 0000349A EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2473 0000349C 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2474 0000349E 7445                <1> 	jz	short com_eoi 	; no
  2475 000034A0 B0FF                <1> 	mov 	al, 0FFh   	; response			
  2476 000034A2 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2477 000034A6 EE                  <1> 	out	dx, al	   	; send on serial port
  2478                              <1> 	; 17/11/2015
  2479 000034A7 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2480 000034AA 7502                <1> 	jne 	short com_i1    ; no
  2481 000034AC 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2482                              <1> com_i1:
  2483                              <1> 	; 17/11/2015
  2484                              <1> 	; reset request for response status (again)
  2485 000034AE FE8B[FC6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2486 000034B4 EB2F                <1> 	jmp	short com_eoi
  2487                              <1> com_i2:	
  2488                              <1> 	; 08/11/2015
  2489 000034B6 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2490 000034B8 7417                <1> 	je	short com_i3	; (check for response signal)
  2491                              <1> 	; 07/11/2015
  2492 000034BA 3C04                <1> 	cmp	al, 04h	; EOT
  2493 000034BC 751C                <1> 	jne	short com_i4	
  2494                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2495                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2496                              <1> 	; 08/11/2015
  2497                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2498 000034BE 861D[C66B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2499 000034C4 E80BFFFFFF          <1> 	call 	ctrlbrk
  2500 000034C9 861D[C66B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2501                              <1> 	;mov	al, 04h ; EOT
  2502                              <1> 	; 08/11/2015
  2503 000034CF EB09                <1> 	jmp	short com_i4	
  2504                              <1> com_i3:
  2505                              <1> 	; 08/11/2015
  2506                              <1> 	; If 0FFh has been received just after a query
  2507                              <1> 	; (schar, ZERO), it is a response signal.
  2508                              <1> 	; 17/11/2015
  2509 000034D1 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2510 000034D4 7704                <1> 	ja	short com_i4 ; no
  2511                              <1> 	; reset query status (schar)
  2512 000034D6 8807                <1> 	mov	[edi], al ; 0FFh
  2513 000034D8 FEC0                <1> 	inc	al ; 0
  2514                              <1> com_i4:
  2515                              <1> 	; 27/07/2014
  2516                              <1> 	; 09/07/2014
  2517 000034DA D0E3                <1> 	shl	bl, 1	
  2518 000034DC 81C3[C86B0000]      <1> 	add	ebx, ttychr
  2519                              <1> 	; 23/07/2014 (always overwrite)
  2520                              <1> 	;;cmp	word [ebx], 0
  2521                              <1> 	;;ja	short com_eoi
  2522                              <1> 	;
  2523 000034E2 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2524                              <1> 			    ; scan code = 0
  2525                              <1> com_eoi:
  2526                              <1> 	;mov	al, 20h
  2527                              <1> 	;out	20h, al	   ; end of interrupt
  2528                              <1> 	;
  2529                              <1> 	; 07/11/2015
  2530                              <1>       	;pop	eax ; *
  2531 000034E5 A0[066C0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2532                              <1> 	; al = tty number (8 or 9)
  2533 000034EA E8F31A0000          <1>         call	wakeup
  2534                              <1> com_iret:
  2535                              <1> 	; 23/10/2015
  2536 000034EF 5A                  <1> 	pop	edx ; **
  2537 000034F0 59                  <1> 	pop	ecx ; ***
  2538                              <1> 	; 18/11/2015
  2539                              <1> 	;pop	eax ; ****
  2540                              <1> 	;mov	cr3, eax
  2541                              <1> 	;jmp	iiret
  2542 000034F1 E9C4D4FFFF          <1> 	jmp	iiretp
  2543                              <1> 
  2544                              <1> ;hfgchr:
  2545                              <1> ;	db '0123456789ABCDEF?*'
  2546                              <1> ;	db 0
  2547                              <1> 
  2548                              <1> ;iiretp: ; 01/09/2015
  2549                              <1> ;	; 28/08/2015
  2550                              <1> ;	pop	eax ; (*) page directory
  2551                              <1> ;	mov	cr3, eax
  2552                              <1> ;iiret:
  2553                              <1> ;	; 22/08/2014
  2554                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2555                              <1> ;	out	20h, al	; 8259 PORT
  2556                              <1> ;	;
  2557                              <1> ;	pop	es
  2558                              <1> ;	pop	ds
  2559                              <1> ;	pop	edi
  2560                              <1> ;	pop	esi
  2561                              <1> ;	pop	ebx ; 29/08/2014
  2562                              <1> ;	pop 	eax
  2563                              <1> ;	iretd
  2564                              <1> 
  2565                              <1> sp_init:
  2566                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2567                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2568                              <1> 	; 07/11/2015
  2569                              <1> 	; 29/10/2015
  2570                              <1> 	; 26/10/2015
  2571                              <1> 	; 23/10/2015
  2572                              <1> 	; 29/06/2015
  2573                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2574                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2575                              <1> 	; Initialization of Serial Port Communication Parameters
  2576                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2577                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2578                              <1> 	;
  2579                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2580                              <1> 	;
  2581                              <1> 	; INPUT:  (29/06/2015)
  2582                              <1> 	;	AL = 0 for COM1
  2583                              <1> 	;	     1 for COM2
  2584                              <1> 	;	AH = Communication parameters	
  2585                              <1> 	;
  2586                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2587                              <1> 	;	Bit	4	3	2	1	0
  2588                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2589                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2590                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2591                              <1> 	;		11 = even
  2592                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2593                              <1> 	;		Retro UNIX 386 v1 feature only !
  2594                              <1> 	;	Bit	7    6    5  | Baud rate
  2595                              <1> 	;		------------------------
  2596                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2597                              <1> 	;		0    0    1  | 9600 (12)
  2598                              <1> 	;		0    1    0  | 19200 (6) 
  2599                              <1> 	;		0    1	  1  | 38400 (3) 
  2600                              <1> 	;		1    0	  0  | 14400 (8)
  2601                              <1> 	;		1    0	  1  | 28800 (4)
  2602                              <1> 	;		1    1    0  | 57600 (2)
  2603                              <1> 	;		1    1    1  | 115200 (1) 	
  2604                              <1> 	
  2605                              <1> 	; References:	
  2606                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2607                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2608                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2609                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2610                              <1> 	;
  2611                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2612                              <1> 	;
  2613 000034F6 BB[026C0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2614 000034FB 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2615                              <1> 	; 29/10/2015
  2616 000034FF 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2617 00003503 E84F000000          <1> 	call	sp_i3	; call A4	
  2618 00003508 A880                <1> 	test	al, 80h
  2619 0000350A 740E                <1> 	jz	short sp_i0 ; OK..
  2620                              <1> 		; Error !
  2621                              <1> 	;mov	dx, 3F8h
  2622 0000350C 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2623                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2624                              <1> 	; 08/01/2022
  2625 0000350F B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2626 00003511 E841000000          <1> 	call	sp_i3	; call A4	
  2627 00003516 A880                <1> 	test	al, 80h
  2628 00003518 7508                <1> 	jnz	short sp_i1
  2629                              <1> sp_i0:
  2630                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2631                              <1>         ; (INT 14h initialization code disables interrupts.)
  2632                              <1> 	;
  2633 0000351A C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2634 0000351D E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2635                              <1> sp_i1:
  2636 00003522 43                  <1> 	inc	ebx
  2637 00003523 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2638                              <1> 	; 29/10/2015
  2639                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2640                              <1> 	; 08/01/2022
  2641 00003527 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2642 00003529 E829000000          <1> 	call	sp_i3	; call A4	
  2643 0000352E A880                <1> 	test	al, 80h
  2644 00003530 740E                <1> 	jz	short sp_i2 ; OK..
  2645                              <1> 		; Error !
  2646                              <1> 	;mov	dx, 2F8h
  2647 00003532 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2648                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2649                              <1> 	; 08/01/2022
  2650 00003535 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2651 00003537 E81B000000          <1> 	call	sp_i3	; call A4	
  2652 0000353C A880                <1> 	test	al, 80h
  2653 0000353E 7516                <1> 	jnz	short sp_i7
  2654                              <1> sp_i2:
  2655 00003540 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2656                              <1> sp_i6:
  2657                              <1> 	;; COM2 - enabling IRQ 3
  2658                              <1> 	; 08/01/2022
  2659 00003543 B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2660                              <1> 	; 07/11/2015
  2661                              <1> 	; 26/10/2015
  2662                              <1> 	;pushf
  2663                              <1> 	;cli
  2664                              <1> 	;;
  2665                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2666                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2667                              <1> 	;in	al, dx 	   		; read register
  2668                              <1> 	;JMP	$+2	   		; I/O DELAY
  2669                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2670                              <1> 	;out	dx, al     		; write back to register
  2671                              <1> 	;JMP	$+2	   		; I/O DELAY
  2672                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2673                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2674                              <1> 	;in	al, dx     		; read register
  2675                              <1> 	;JMP	$+2	   		; I/O DELAY
  2676                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2677                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2678                              <1> 	;out	dx, al 	   		; write back to register
  2679                              <1> 	;JMP	$+2        		; I/O DELAY
  2680                              <1> 	;in	al, 21h    		; read interrupt mask register
  2681                              <1> 	;JMP	$+2	   		; I/O DELAY
  2682                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2683                              <1> 	;out	21h, al    		; write back to register
  2684                              <1> 	;
  2685                              <1> 	; 08/01/2022
  2686 00003545 9C                  <1> 	pushf
  2687 00003546 E8AA000000          <1> 	call	sp_i8
  2688                              <1> 	; 23/10/2015
  2689 0000354B B8[2A340000]        <1> 	mov 	eax, com2_int
  2690 00003550 A3[DE390000]        <1> 	mov	[com2_irq3], eax
  2691                              <1> 	; 26/10/2015
  2692 00003555 9D                  <1> 	popf	
  2693                              <1> sp_i7:
  2694 00003556 C3                  <1> 	retn
  2695                              <1> 
  2696                              <1> sp_i3:
  2697                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2698                              <1> 	; 28/10/2015
  2699 00003557 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2700 00003559 B000                <1> 	mov	al, 0
  2701 0000355B EE                  <1> 	out	dx, al			; disable serial port interrupt
  2702 0000355C EB00                <1> 	JMP	$+2			; I/O DELAY
  2703 0000355E 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2704 00003561 B080                <1> 	mov	al, 80h			
  2705 00003563 EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2706                              <1> 	;-----	SET BAUD RATE DIVISOR
  2707                              <1> 	; 26/10/2015
  2708 00003564 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2709                              <1> 					; of the divisor value
  2710 00003567 88C8                <1> 	mov	al, cl	; 1
  2711 00003569 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2712                              <1> 					; 2 = 57600 baud
  2713                              <1> 					; 3 = 38400 baud
  2714                              <1> 					; 6 = 19200 baud
  2715                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2716 0000356A EB00                <1> 	JMP	$+2			; I/O DELAY
  2717 0000356C 28C0                <1> 	sub	al, al
  2718 0000356E FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2719                              <1> 					; of the divisor value
  2720 00003570 EE                  <1> 	out	dx, al ; 0
  2721 00003571 EB00                <1> 	JMP	$+2			; I/O DELAY
  2722                              <1> 	;	
  2723 00003573 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2724                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2725 00003575 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2726 00003578 EE                  <1> 	out	dx, al			
  2727 00003579 EB00                <1> 	JMP	$+2			; I/O DELAY
  2728                              <1> 	; 29/10/2015
  2729 0000357B FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2730 0000357D 30C0                <1> 	xor	al, al			; 0
  2731 0000357F EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2732 00003580 EB00                <1> 	JMP	$+2	
  2733                              <1> sp_i4:
  2734                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2735                              <1> 	; 29/06/2015 (line status after modem status)
  2736 00003582 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2737                              <1> sp_i4s:
  2738 00003585 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2739 00003586 EB00                <1> 	JMP	$+2			; I/O DELAY
  2740 00003588 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2741 0000358A FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2742                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2743 0000358C EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2744                              <1> 	; AL = Line status, AH = Modem status
  2745 0000358D C3                  <1> 	retn
  2746                              <1> 
  2747                              <1> sp_status:
  2748                              <1> 	; 29/06/2015
  2749                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2750                              <1> 	; Get serial port status
  2751 0000358E 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2752 00003592 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2753                              <1> 					; dx = 2FEh for COM2
  2754 00003594 EBEF                <1> 	jmp	short sp_i4s
  2755                              <1> 
  2756                              <1> sp_setp: ; Set serial port communication parameters
  2757                              <1> 	; 04/02/2022 
  2758                              <1> 	;	(Retro UNIX 386 v1, Kernel v0.2.0.18)
  2759                              <1> 	; 08/01/2022
  2760                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2761                              <1> 	; 07/11/2015
  2762                              <1> 	; 29/10/2015
  2763                              <1> 	; 29/06/2015
  2764                              <1> 	; Retro UNIX 386 v1 feature only !	
  2765                              <1> 	;
  2766                              <1> 	; INPUT:
  2767                              <1> 	;	AL = 0 for COM1
  2768                              <1> 	;	     1 for COM2
  2769                              <1> 	;	AH = Communication parameters (*)
  2770                              <1> 	; OUTPUT:
  2771                              <1> 	;	CL = Line status
  2772                              <1> 	;	CH = Modem status
  2773                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2774                              <1> 	;		 'invalid parameter !' 
  2775                              <1> 	;		 	 or
  2776                              <1> 	;		 'device not ready !' error
  2777                              <1> 	;	
  2778                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2779                              <1> 	;	Bit	4	3	2	1	0
  2780                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2781                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2782                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2783                              <1> 	;		11 = even
  2784                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2785                              <1> 	;		Retro UNIX 386 v1 feature only !
  2786                              <1> 	;	Bit	7    6    5  | Baud rate
  2787                              <1> 	;		------------------------
  2788                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2789                              <1> 	;		0    0    1  | 9600 (12)
  2790                              <1> 	;		0    1    0  | 19200 (6) 
  2791                              <1> 	;		0    1	  1  | 38400 (3) 
  2792                              <1> 	;		1    0	  0  | 14400 (8)
  2793                              <1> 	;		1    0	  1  | 28800 (4)
  2794                              <1> 	;		1    1    0  | 57600 (2)
  2795                              <1> 	;		1    1    1  | 115200 (1) 
  2796                              <1> 	;
  2797                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2798                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2799                              <1> 	;
  2800                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2801                              <1> 	;
  2802 00003596 66BAF803            <1> 	mov	dx, 3F8h
  2803 0000359A BB[026C0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2804 0000359F 3C01                <1> 	cmp	al, 1
  2805 000035A1 7770                <1> 	ja 	short sp_invp_err
  2806 000035A3 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2807 000035A5 FECE                <1> 	dec	dh ; 2F8h
  2808 000035A7 43                  <1> 	inc	ebx ; COM2 control byte offset
  2809                              <1> sp_setp1:
  2810                              <1> 	; 29/10/2015
  2811 000035A8 8823                <1> 	mov	[ebx], ah
  2812 000035AA 0FB6CC              <1> 	movzx 	ecx, ah
  2813 000035AD C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2814 000035B0 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2815 000035B3 8A81[22360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2816 000035B9 6689C1              <1> 	mov	cx, ax
  2817 000035BC E896FFFFFF          <1> 	call	sp_i3
  2818 000035C1 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2819 000035C4 A880                <1> 	test	al, 80h
  2820 000035C6 740F                <1> 	jz	short sp_setp2
  2821 000035C8 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2822                              <1> stp_dnr_err:
  2823 000035CB C705[AB6F0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2823 000035D3 0000                <1>
  2824                              <1> 	; CL = Line status, CH = Modem status
  2825 000035D5 F9                  <1> 	stc
  2826 000035D6 C3                  <1> 	retn
  2827                              <1> sp_setp2:
  2828 000035D7 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2829                              <1>         ;jna	sp_i6
  2830                              <1> 		      ; COM1 (3F?h)
  2831                              <1> 	; 24/12/2021
  2832 000035DA 7705                <1> 	ja	short sp_i5
  2833 000035DC E962FFFFFF          <1> 	jmp	sp_i6
  2834                              <1> sp_i5: 
  2835                              <1> 	; 08/01/2022
  2836 000035E1 B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2837                              <1> 	; 07/11/2015
  2838                              <1> 	; 26/10/2015
  2839                              <1> 	; 29/06/2015
  2840                              <1> 	;
  2841                              <1> 	;; COM1 - enabling IRQ 4
  2842                              <1> 	;pushf
  2843                              <1> 	;cli
  2844                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2845                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2846                              <1> 	;in	al, dx 	   		; read register
  2847                              <1> 	;JMP	$+2			; I/O DELAY
  2848                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2849                              <1> 	;out	dx, al     		; write back to register
  2850                              <1> 	;JMP	$+2			; I/O DELAY
  2851                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2852                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2853                              <1> 	;in	al, dx     		; read register
  2854                              <1> 	;JMP	$+2			; I/O DELAY
  2855                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2856                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2857                              <1> 	;out	dx, al 	   		; write back to register
  2858                              <1> 	;JMP	$+2        		; I/O DELAY
  2859                              <1> 	;in	al, 21h    		; read interrupt mask register
  2860                              <1> 	;JMP	$+2			; I/O DELAY
  2861                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2862                              <1> 	;out	21h, al    		; write back to register
  2863                              <1> 	;
  2864                              <1> 	; 08/01/2022
  2865 000035E3 9C                  <1> 	pushf
  2866 000035E4 E80C000000          <1> 	call	sp_i8
  2867                              <1> 	; 23/10/2015
  2868 000035E9 B8[33340000]        <1> 	mov 	eax, com1_int
  2869 000035EE A3[DA390000]        <1> 	mov	[com1_irq4], eax
  2870                              <1> 	; 26/10/2015
  2871 000035F3 9D                  <1> 	popf
  2872 000035F4 C3                  <1> 	retn
  2873                              <1> 
  2874                              <1> sp_i8:
  2875                              <1> 	; 08/01/2022
  2876                              <1> 	;pushf
  2877 000035F5 FA                  <1> 	cli
  2878                              <1> 	;
  2879                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2880 000035F6 B2FC                <1> 	mov	dl, 0FCh
  2881 000035F8 EC                  <1> 	in	al, dx 	   		; read register
  2882 000035F9 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2883 000035FB 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2884 000035FD EE                  <1> 	out	dx, al     		; write back to register
  2885 000035FE EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2886                              <1> 	;mov	dx, 2F9h  ; 3F9h 		; interrupt enable register
  2887 00003600 B2F9                <1> 	mov	dl, 0F9h
  2888 00003602 EC                  <1> 	in	al, dx     		; read register
  2889 00003603 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2890                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2891 00003605 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2892 00003607 EE                  <1> 	out	dx, al 	   		; write back to register
  2893 00003608 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2894 0000360A E421                <1> 	in	al, 21h    		; read interrupt mask register
  2895 0000360C EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2896                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2897 0000360E 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2898 00003610 E621                <1> 	out	21h, al    		; write back to register
  2899                              <1> 	;
  2900                              <1> 	;popf	
  2901 00003612 C3                  <1> 	retn
  2902                              <1> 
  2903                              <1> sp_invp_err:
  2904 00003613 C705[AB6F0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2904 0000361B 0000                <1>
  2905 0000361D 31C9                <1> 	xor	ecx, ecx
  2906 0000361F 49                  <1> 	dec	ecx ; 0FFFFh
  2907 00003620 F9                  <1> 	stc
  2908 00003621 C3                  <1> 	retn
  2909                              <1> 
  2910                              <1> ; 29/10/2015
  2911                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2912 00003622 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2913                              <1> 
  2914                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2915                              <1> epoch:
  2916                              <1> 	; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2917                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2918                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2919                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2920                              <1> 	; 'epoch' procedure prototype: 
  2921                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2922                              <1> 	; 14/11/2012
  2923                              <1> 	; unixboot.asm (boot file configuration)
  2924                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2925                              <1> 	; 21/7/2012
  2926                              <1> 	; 15/7/2012
  2927                              <1> 	; 14/7/2012		
  2928                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2929                              <1> 	; compute current date and time as UNIX Epoch/Time
  2930                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2931                              <1> 	;
  2932                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2933                              <1> 	;
  2934 00003629 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2935 0000362E 86E9                <1>         xchg 	ch,cl
  2936 00003630 66890D[02690000]    <1>         mov 	[hour], cx
  2937 00003637 86F2                <1>         xchg 	dh,dl
  2938 00003639 668915[04690000]    <1>         mov 	[second], dx
  2939                              <1> 	;
  2940 00003640 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2941 00003645 86E9                <1>         xchg 	ch,cl
  2942 00003647 66890D[FE680000]    <1>         mov 	[year], cx
  2943 0000364E 86F2                <1>         xchg 	dh,dl
  2944 00003650 668915[00690000]    <1>         mov 	[month], dx
  2945                              <1> 	;
  2946 00003657 66B93030            <1> 	mov 	cx, 3030h
  2947                              <1> 	;
  2948 0000365B A0[02690000]        <1> 	mov 	al, [hour] ; Hour
  2949                              <1>         	; AL <= BCD number)
  2950 00003660 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2951                              <1> 					; AH = AL / 10h
  2952                              <1> 					; AL = AL MOD 10h
  2953 00003662 D50A                <1>         aad 	; AX= AH*10+AL
  2954 00003664 A2[02690000]        <1> 	mov 	[hour], al
  2955 00003669 A0[03690000]        <1> 	mov 	al, [hour+1] ; Minute
  2956                              <1>         	; AL <= BCD number)
  2957 0000366E D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2958                              <1> 					; AH = AL / 10h
  2959                              <1> 					; AL = AL MOD 10h
  2960 00003670 D50A                <1>         aad 	; AX= AH*10+AL
  2961 00003672 A2[03690000]        <1> 	mov 	[minute], al
  2962 00003677 A0[04690000]        <1> 	mov 	al, [second] ; Second
  2963                              <1>         	; AL <= BCD number)
  2964 0000367C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2965                              <1> 					; AH = AL / 10h
  2966                              <1> 					; AL = AL MOD 10h
  2967 0000367E D50A                <1>         aad 	; AX= AH*10+AL
  2968 00003680 A2[04690000]        <1> 	mov 	[second], al
  2969 00003685 66A1[FE680000]      <1> 	mov 	ax, [year] ; Year (century)
  2970                              <1>  	;push 	ax
  2971                              <1> 	; 08/01/2022
  2972 0000368B 50                  <1> 	push	eax
  2973                              <1> 	   	; AL <= BCD number)
  2974 0000368C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2975                              <1> 					; AH = AL / 10h
  2976                              <1> 					; AL = AL MOD 10h
  2977 0000368E D50A                <1>         aad 	; AX= AH*10+AL
  2978 00003690 B464                <1> 	mov 	ah, 100
  2979 00003692 F6E4                <1> 	mul 	ah
  2980 00003694 66A3[FE680000]      <1> 	mov 	[year], ax
  2981                              <1> 	;pop	ax
  2982                              <1> 	; 08/01/2022
  2983 0000369A 58                  <1> 	pop	eax
  2984 0000369B 88E0                <1> 	mov	al, ah
  2985                              <1>         	; AL <= BCD number)
  2986 0000369D D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2987                              <1> 					; AH = AL / 10h
  2988                              <1> 					; AL = AL MOD 10h
  2989 0000369F D50A                <1>         aad 	; AX= AH*10+AL
  2990 000036A1 660105[FE680000]    <1> 	add 	[year], ax
  2991 000036A8 A0[00690000]        <1> 	mov 	al, [month] ; Month
  2992                              <1>            	; AL <= BCD number)
  2993 000036AD D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2994                              <1> 					; AH = AL / 10h
  2995                              <1> 					; AL = AL MOD 10h
  2996 000036AF D50A                <1>         aad 	; AX= AH*10+AL
  2997 000036B1 A2[00690000]        <1> 	mov 	[month], al	
  2998 000036B6 A0[01690000]        <1>         mov     al, [month+1]      	; Day
  2999                              <1>            	; AL <= BCD number)
  3000 000036BB D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3001                              <1> 					; AH = AL / 10h
  3002                              <1> 					; AL = AL MOD 10h
  3003 000036BD D50A                <1>         aad 	; AX= AH*10+AL
  3004 000036BF A2[01690000]        <1>         mov     [day], al
  3005                              <1> 	
  3006                              <1> convert_to_epoch:
  3007                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3008                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  3009                              <1> 	;
  3010                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3011                              <1> 	;
  3012                              <1> 	; Derived from DALLAS Semiconductor
  3013                              <1> 	; Application Note 31 (DS1602/DS1603)
  3014                              <1> 	; 6 May 1998
  3015 000036C4 29C0                <1> 	sub 	eax, eax
  3016 000036C6 66A1[FE680000]      <1> 	mov 	ax, [year]
  3017 000036CC 662DB207            <1> 	sub 	ax, 1970
  3018 000036D0 BA6D010000          <1> 	mov 	edx, 365
  3019 000036D5 F7E2                <1> 	mul 	edx
  3020 000036D7 31DB                <1> 	xor 	ebx, ebx
  3021 000036D9 8A1D[00690000]      <1> 	mov 	bl, [month]
  3022 000036DF FECB                <1> 	dec 	bl
  3023 000036E1 D0E3                <1> 	shl 	bl, 1
  3024                              <1> 	;sub	edx, edx
  3025 000036E3 668B93[06690000]    <1> 	mov 	dx, [EBX+DMonth]
  3026 000036EA 8A1D[01690000]      <1>         mov     bl, [day]
  3027 000036F0 FECB                <1> 	dec 	bl
  3028 000036F2 01D0                <1> 	add 	eax, edx
  3029 000036F4 01D8                <1> 	add 	eax, ebx
  3030                              <1> 			; EAX = days since 1/1/1970
  3031 000036F6 668B15[FE680000]    <1> 	mov 	dx, [year]
  3032 000036FD 6681EAB107          <1> 	sub 	dx, 1969
  3033 00003702 66D1EA              <1> 	shr 	dx, 1
  3034 00003705 66D1EA              <1> 	shr 	dx, 1		
  3035                              <1> 		; (year-1969)/4
  3036 00003708 01D0                <1> 	add 	eax, edx
  3037                              <1> 			; + leap days since 1/1/1970
  3038 0000370A 803D[00690000]02    <1> 	cmp 	byte [month], 2	; if past february
  3039 00003711 7610                <1> 	jna 	short cte1
  3040 00003713 668B15[FE680000]    <1> 	mov 	dx, [year]
  3041 0000371A 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3042 0000371E 7503                <1> 	jnz 	short cte1		
  3043                              <1> 			; and if leap year
  3044 00003720 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3045                              <1> cte1: 			; compute seconds since 1/1/1970
  3046 00003723 BA18000000          <1> 	mov 	edx, 24
  3047 00003728 F7E2                <1> 	mul	edx
  3048 0000372A 8A15[02690000]      <1> 	mov 	dl, [hour]
  3049 00003730 01D0                <1> 	add 	eax, edx
  3050                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3051                              <1> 	;mov	ebx, 60
  3052 00003732 B33C                <1> 	mov	bl, 60
  3053 00003734 F7E3                <1> 	mul	ebx
  3054 00003736 8A15[03690000]      <1> 	mov 	dl, [minute]
  3055 0000373C 01D0                <1> 	add 	eax, edx
  3056                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3057                              <1> 	;mov 	ebx, 60
  3058 0000373E F7E3                <1> 	mul	ebx
  3059 00003740 8A15[04690000]      <1> 	mov 	dl, [second]
  3060 00003746 01D0                <1> 	add 	eax, edx
  3061                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3062 00003748 C3                  <1> 	retn
  3063                              <1> 
  3064                              <1> get_rtc_time:
  3065                              <1> 	; 15/03/2015
  3066                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	:
  3067                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	:
  3068                              <1> 	; INT 1Ah						:
  3069                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3070                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3071                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3072                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3073                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3074                              <1> 	;								
  3075                              <1> RTC_20: 			; GET RTC TIME
  3076 00003749 FA                  <1> 	cli
  3077 0000374A E809D4FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3078 0000374F 7227                <1> 	JC	short RTC_29	; EXIT IF ERROR (CY= 1)
  3079                              <1> 
  3080 00003751 B000                <1> 	MOV	AL,CMOS_SECONDS ; SET ADDRESS OF SECONDS
  3081 00003753 E8E8D3FFFF          <1> 	CALL	CMOS_READ	; GET SECONDS
  3082 00003758 88C6                <1> 	MOV	DH,AL		; SAVE
  3083 0000375A B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3084 0000375C E8DFD3FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3085 00003761 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3086 00003763 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3087 00003765 B002                <1> 	MOV	AL,CMOS_MINUTES ; SET ADDRESS OF MINUTES
  3088 00003767 E8D4D3FFFF          <1> 	CALL	CMOS_READ	; GET MINUTES
  3089 0000376C 88C1                <1> 	MOV	CL,AL		; SAVE
  3090 0000376E B004                <1> 	MOV	AL,CMOS_HOURS	; SET ADDRESS OF HOURS
  3091 00003770 E8CBD3FFFF          <1> 	CALL	CMOS_READ	; GET HOURS
  3092 00003775 88C5                <1> 	MOV	CH,AL		; SAVE
  3093 00003777 F8                  <1> 	CLC			; SET CY= 0
  3094                              <1> RTC_29:
  3095 00003778 FB                  <1> 	sti
  3096 00003779 C3                  <1> 	RETn			; RETURN WITH RESULT IN CARRY FLAG
  3097                              <1> 
  3098                              <1> get_rtc_date:
  3099                              <1> 	; 15/03/2015
  3100                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	       :
  3101                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	       :
  3102                              <1> 	; INT 1Ah						       :
  3103                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3104                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3105                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3106                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3107                              <1> 	;      (DL) = DAY IN BCD (01-31).			       :		
  3108                              <1> 	;
  3109                              <1> RTC_40: 			; GET RTC DATE
  3110 0000377A FA                  <1> 	cli
  3111 0000377B E8D8D3FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3112 00003780 7225                <1> 	JC	short RTC_49	; EXIT IF ERROR (CY= 1)
  3113                              <1> 
  3114 00003782 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH
  3115 00003784 E8B7D3FFFF          <1> 	CALL	CMOS_READ	; READ DAY OF MONTH
  3116 00003789 88C2                <1> 	MOV	DL,AL		; SAVE
  3117 0000378B B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH
  3118 0000378D E8AED3FFFF          <1> 	CALL	CMOS_READ	; READ MONTH
  3119 00003792 88C6                <1> 	MOV	DH,AL		; SAVE
  3120 00003794 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR
  3121 00003796 E8A5D3FFFF          <1> 	CALL	CMOS_READ	; READ YEAR
  3122 0000379B 88C1                <1> 	MOV	CL,AL		; SAVE
  3123 0000379D B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY LOCATION
  3124 0000379F E89CD3FFFF          <1> 	CALL	CMOS_READ	; GET CENTURY BYTE
  3125 000037A4 88C5                <1> 	MOV	CH,AL		; SAVE
  3126 000037A6 F8                  <1> 	CLC			; SET CY=0
  3127                              <1> RTC_49:
  3128 000037A7 FB                  <1> 	sti
  3129 000037A8 C3                  <1> 	RETn			; RETURN WITH RESULTS IN CARRY FLAG
  3130                              <1> 
  3131                              <1> set_date_time:
  3132                              <1> convert_from_epoch:
  3133                              <1> 	; 02/06/2022
  3134                              <1> 	; 01/06/2022 (BugFix)
  3135                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3136                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3137                              <1> 	; 'convert_from_epoch' procedure prototype:
  3138                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3139                              <1> 	;
  3140                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))
  3141                              <1> 	;
  3142                              <1> 	; Derived from DALLAS Semiconductor
  3143                              <1> 	; Application Note 31 (DS1602/DS1603)
  3144                              <1> 	; 6 May 1998
  3145                              <1> 	;
  3146                              <1> 	; INPUT:
  3147                              <1> 	; EAX = Unix (Epoch) Time
  3148                              <1> 	;
  3149 000037A9 31D2                <1> 	xor 	edx, edx
  3150                              <1> 	; 02/06/2022
  3151 000037AB 31C9                <1> 	xor	ecx, ecx
  3152 000037AD 31DB                <1> 	xor	ebx, ebx
  3153                              <1> 	;mov 	ecx, 60
  3154 000037AF B13C                <1> 	mov	cl, 60
  3155 000037B1 F7F1                <1> 	div	ecx
  3156                              <1> 	;mov 	[imin], eax  ; whole minutes
  3157                              <1> 			     ; since 1/1/1970
  3158                              <1> 	;mov 	[second], dx ; leftover seconds
  3159 000037B3 8815[04690000]      <1> 	mov	[second], dl ; 02/06/2022
  3160 000037B9 29D2                <1> 	sub 	edx, edx
  3161 000037BB F7F1                <1> 	div	ecx
  3162                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3163                              <1> 	;		     ; since 1/1/1970
  3164                              <1> 	;mov 	[minute], dx ; leftover minutes
  3165 000037BD 8815[03690000]      <1> 	mov	[minute], dl ; 02/06/2022
  3166 000037C3 31D2                <1> 	xor	edx, edx
  3167                              <1> 	;mov 	cx, 24
  3168 000037C5 B118                <1> 	mov 	cl, 24
  3169 000037C7 F7F1                <1> 	div	ecx
  3170                              <1> 	;mov 	[iday], ax   ; whole days
  3171                              <1> 			     ; since 1/1/1970
  3172                              <1> 	;mov 	[hour], dx   ; leftover hours
  3173 000037C9 8815[02690000]      <1> 	mov	[hour], dl   ; 02/06/2022
  3174                              <1> 
  3175 000037CF 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3176                              <1> 			     ; 1/1/1968 	
  3177                              <1> 	;mov 	[iday], ax
  3178 000037D4 50                  <1> 	push 	eax
  3179 000037D5 29D2                <1> 	sub	edx, edx
  3180 000037D7 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3181 000037DC F7F1                <1> 	div	ecx
  3182 000037DE 59                  <1> 	pop 	ecx
  3183                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3184                              <1> 	;push	dx
  3185                              <1> 	; 01/06/2022
  3186 000037DF 52                  <1> 	push 	edx
  3187                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3188 000037E0 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3189 000037E4 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3190 000037E5 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3191                              <1> 	;mov 	[lday], ax   ; since 1968
  3192                              <1> 	;mov 	cx, [iday]
  3193 000037E8 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday
  3194 000037E9 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3195 000037EB B96D010000          <1> 	mov 	ecx, 365
  3196 000037F0 31D2                <1> 	xor	edx, edx
  3197                              <1> 	; EAX = iday-lday, EDX = 0
  3198 000037F2 F7F1                <1> 	div	ecx
  3199                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3200                              <1> 	;jday = iday - (iyrs*365) - lday
  3201                              <1> 	;mov	[jday], dx   ; days since 1/1 of current year
  3202                              <1> 	;add	eax, 1968
  3203 000037F4 6605B007            <1> 	add 	ax, 1968     ; compute year
  3204 000037F8 66A3[FE680000]      <1> 	mov 	[year], ax
  3205                              <1> 	;mov 	cx, dx
  3206                              <1> 	; 02/06/2022
  3207 000037FE 89D1                <1> 	mov	ecx, edx
  3208                              <1> 	;mov 	dx, [qday]
  3209                              <1> 	;pop	dx
  3210                              <1> 	; 01/06/2022
  3211 00003800 5A                  <1> 	pop 	edx
  3212 00003801 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3213 00003806 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3214 00003808 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3215 0000380C F5                  <1>         cmc		     ; add a leap day to the # of whole
  3216 0000380D 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3217                              <1> cfe1:			
  3218                              <1> 	;mov 	[jday], cx
  3219                              <1> 	;mov 	bx, 12       ; estimate month
  3220                              <1> 	;sub	ebx, ebx
  3221                              <1> 	; 02/06/2022
  3222 00003811 B30C                <1> 	mov	bl, 12
  3223 00003813 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3224 00003817 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3225                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3226                              <1> 	;cmp 	cx, dx       ; mday = # of days passed from 1/1
  3227                              <1> 	; 02/06/2022
  3228 0000381B 39D1                <1> 	cmp	ecx, edx 	 		
  3229 0000381D 7319                <1> 	jnb 	short cfe3
  3230                              <1> 	;dec 	bx           ; month = month - 1
  3231 0000381F FECB                <1> 	dec	bl			
  3232                              <1> 	;shl 	bx, 1
  3233 00003821 D0E3                <1> 	shl	bl, 1
  3234 00003823 668B93[06690000]    <1> 	mov 	dx, [ebx+DMonth] ; # elapsed days at 1st of month
  3235                              <1> 	;shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3236                              <1> 	; 02/06/2022
  3237 0000382A D0EB                <1> 	shr	bl, 1
  3238 0000382C 80FB01              <1> 	cmp	bl, 1
  3239                              <1> 	;cmp	bx, 1        ; if month > 2 and year mod 4  = 0
  3240 0000382F 76EA                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3241 00003831 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3242 00003833 75E6                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3243                              <1> 	;inc 	dx           ; mday = mday + 1
  3244 00003835 42                  <1> 	inc	edx
  3245 00003836 EBE3                <1> 	jmp 	short cfe2
  3246                              <1> cfe3:
  3247                              <1> 	;inc 	bx	     ; -> bx = month, 1 to 12
  3248                              <1> 	; 02/06/2022
  3249 00003838 FEC3                <1> 	inc	bl
  3250                              <1> 	;mov 	[month], bx
  3251 0000383A 881D[00690000]      <1> 	mov	[month], bl
  3252                              <1> 	;sub 	cx, dx	     ; day = jday - mday + 1
  3253 00003840 29D1                <1> 	sub	ecx, edx
  3254                              <1> 	;inc 	cx
  3255 00003842 FEC1                <1> 	inc	cl
  3256                              <1> 	;mov 	[day], cx
  3257 00003844 880D[01690000]      <1> 	mov	[day], cl    ; 02/06/2022
  3258                              <1> 	
  3259                              <1> 	; eax, ebx, ecx, edx is changed at return
  3260                              <1> 	; output ->
  3261                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3262                              <1> 	
  3263                              <1> 	; 01/06/2022 (BugFix)
  3264                              <1> _set_date:
  3265 0000384A 66A1[FE680000]      <1> 	mov	ax, [year]
  3266 00003850 B520                <1> 	mov	ch, 20h ; century (bcd)
  3267 00003852 662DD007            <1> 	sub	ax, 2000
  3268 00003856 7306                <1> 	jnc	short set_date
  3269 00003858 B519                <1> 	mov	ch, 19h ; century (bcd) 
  3270 0000385A 6683C064            <1> 	add	ax, 100	
  3271                              <1> 	; 01/06/2022
  3272                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3273                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3274                              <1> set_date:
  3275                              <1>         ;mov	al, [year+1]
  3276                              <1> 	;aam 	; ah = al / 10, al = al mod 10
  3277                              <1> 	;db 	0D5h, 10h    ; Undocumented inst. AAD
  3278                              <1> 	;		     ; AL = AH * 10h + AL
  3279                              <1> 	;mov 	ch, al ; century (BCD)
  3280                              <1> 	;mov 	al, [year]
  3281                              <1> 	; al = year (0-99) ; 01/06/2022
  3282 0000385E D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3283 00003860 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3284                              <1> 			     ; AL = AH * 10h + AL
  3285 00003862 88C1                <1> 	mov 	cl, al ; year (BCD)
  3286 00003864 A0[00690000]        <1>         mov 	al, [month]
  3287 00003869 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3288 0000386B D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3289                              <1> 			     ; AL = AH * 10h + AL
  3290 0000386D 88C6                <1> 	mov 	dh, al ; month (BCD)
  3291 0000386F A0[01690000]        <1> 	mov 	al, [day]
  3292 00003874 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3293 00003876 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3294                              <1> 			     ; AL = AH * 10h + AL
  3295                              <1> 	; 01/06/2022 (BugFix)
  3296 00003878 88C2                <1> 	mov 	dl, al ; day (BCD)
  3297                              <1> 
  3298                              <1> 	; Set real-time clock date
  3299 0000387A E879000000          <1> 	call	set_rtc_date
  3300                              <1> set_time:
  3301                              <1>         ; Read real-time clock time 
  3302                              <1> 	; (get day light saving time bit status)
  3303 0000387F FA                  <1>  	cli
  3304 00003880 E8D3D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3305                              <1> 	; cf = 1 -> al = 0
  3306 00003885 7207                <1>         jc      short stime1
  3307 00003887 B00B                <1> 	MOV	AL,CMOS_REG_B	; ADDRESS ALARM REGISTER
  3308 00003889 E8B2D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3309                              <1> stime1:
  3310 0000388E FB                  <1> 	sti
  3311 0000388F 2401                <1> 	AND	AL,00000001B	; MASK FOR VALID DSE BIT
  3312 00003891 88C2                <1> 	MOV	DL,AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3313                              <1> 	; DL = 1 or 0 (day light saving time)
  3314                              <1> 	;	
  3315 00003893 A0[02690000]        <1> 	mov 	al, [hour]
  3316 00003898 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3317 0000389A D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3318                              <1> 			     ; AL = AH * 10h + AL
  3319 0000389C 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3320 0000389E A0[03690000]        <1>         mov     al, [minute]
  3321 000038A3 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3322 000038A5 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3323                              <1> 			     ; AL = AH * 10h + AL
  3324 000038A7 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3325 000038A9 A0[04690000]        <1>         mov     al, [second]
  3326 000038AE D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3327 000038B0 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3328                              <1> 			     ; AL = AH * 10h + AL
  3329 000038B2 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3330                              <1> 
  3331                              <1> 	; Set real-time clock time
  3332                              <1>  	; call	set_rtc_time
  3333                              <1> set_rtc_time:
  3334                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)		  :
  3335                              <1> 	; 15/03/2015							  :
  3336                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code		  :
  3337                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES		  :
  3338                              <1> 	; INT 1Ah							  :
  3339                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			  :
  3340                              <1> 	;      (CH) = HOURS IN BCD (00-23)			          :
  3341                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			          :
  3342                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			          :
  3343                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.      :
  3344                              <1> 	;								  :
  3345                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3346                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3347                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3348                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3349                              <1> 	;								  :
  3350                              <1> RTC_30: 			; SET RTC TIME
  3351 000038B4 FA                  <1> 	cli
  3352 000038B5 E89ED2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3353 000038BA 7305                <1> 	JNC	short RTC_35	; GO AROUND IF CLOCK OPERATING
  3354 000038BC E886000000          <1> 	CALL	RTC_STA 	; ELSE TRY INITIALIZING CLOCK
  3355                              <1> RTC_35:
  3356 000038C1 88F4                <1> 	MOV	AH,DH		; GET TIME BYTE - SECONDS
  3357 000038C3 B000                <1> 	MOV	AL,CMOS_SECONDS ; ADDRESS SECONDS
  3358 000038C5 E89D000000          <1> 	CALL	CMOS_WRITE	; UPDATE SECONDS
  3359 000038CA 88CC                <1> 	MOV	AH,CL		; GET TIME BYTE - MINUTES
  3360 000038CC B002                <1> 	MOV	AL,CMOS_MINUTES ; ADDRESS MINUTES
  3361 000038CE E894000000          <1> 	CALL	CMOS_WRITE	; UPDATE MINUTES
  3362 000038D3 88EC                <1> 	MOV	AH,CH		; GET TIME BYTE - HOURS
  3363 000038D5 B004                <1> 	MOV	AL,CMOS_HOURS	; ADDRESS HOURS
  3364 000038D7 E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3365                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3366 000038DC 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3367 000038E0 E85BD2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT TIME
  3368 000038E5 2462                <1> 	AND	AL,01100010B	; MASK FOR VALID BIT POSITIONS
  3369 000038E7 0C02                <1> 	OR	AL,00000010B	; TURN ON 24 HOUR MODE
  3370 000038E9 80E201              <1> 	AND	DL,00000001B	; USE ONLY THE DSE BIT
  3371 000038EC 08D0                <1> 	OR	AL,DL		; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3372 000038EE 86E0                <1> 	XCHG	AH,AL		; PLACE IN WORK REGISTER AND GET ADDRESS
  3373 000038F0 E872000000          <1> 	CALL	CMOS_WRITE	; SET NEW ALARM BITS
  3374 000038F5 F8                  <1> 	CLC			; SET CY= 0
  3375 000038F6 FB                  <1> 	sti
  3376 000038F7 C3                  <1> 	RETn			; RETURN WITH CY= 0
  3377                              <1> 
  3378                              <1> set_rtc_date:
  3379                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)	   :
  3380                              <1> 	; 15/03/2015						   :
  3381                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code	   :
  3382                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES	   :
  3383                              <1> 	; INT 1Ah						   :
  3384                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3385                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3386                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3387                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3388                              <1> 	;     (DL) = DAY IN BCD (01-31).			   :
  3389                              <1> 	;							   :
  3390                              <1> RTC_50: 			; SET RTC DATE
  3391 000038F8 FA                  <1> 	cli
  3392 000038F9 E85AD2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3393 000038FE 7305                <1> 	JNC	short RTC_55	; GO AROUND IF NO ERROR
  3394 00003900 E842000000          <1> 	CALL	RTC_STA 	; ELSE INITIALIZE CLOCK
  3395                              <1> RTC_55:
  3396 00003905 66B80600            <1> 	MOV	AX,CMOS_DAY_WEEK ; ADDRESS OF DAY OF WEEK BYTE
  3397 00003909 E859000000          <1> 	CALL	CMOS_WRITE	; LOAD ZEROS TO DAY OF WEEK
  3398 0000390E 88D4                <1> 	MOV	AH,DL		; GET DAY OF MONTH BYTE
  3399 00003910 B007                <1> 	MOV	AL,CMOS_DAY_MONTH ; ADDRESS DAY OF MONTH BYTE
  3400 00003912 E850000000          <1> 	CALL	CMOS_WRITE	; WRITE OF DAY OF MONTH REGISTER
  3401 00003917 88F4                <1> 	MOV	AH,DH		; GET MONTH
  3402 00003919 B008                <1> 	MOV	AL,CMOS_MONTH	; ADDRESS MONTH BYTE
  3403 0000391B E847000000          <1> 	CALL	CMOS_WRITE	; WRITE MONTH REGISTER
  3404 00003920 88CC                <1> 	MOV	AH,CL		; GET YEAR BYTE
  3405 00003922 B009                <1> 	MOV	AL,CMOS_YEAR	; ADDRESS YEAR REGISTER
  3406 00003924 E83E000000          <1> 	CALL	CMOS_WRITE	; WRITE YEAR REGISTER
  3407 00003929 88EC                <1> 	MOV	AH,CH		; GET CENTURY BYTE
  3408 0000392B B032                <1> 	MOV	AL,CMOS_CENTURY ; ADDRESS CENTURY BYTE
  3409 0000392D E835000000          <1> 	CALL	CMOS_WRITE	; WRITE CENTURY LOCATION
  3410                              <1> 	;MOV	AX,X*CMOS_REG_B ; ADDRESS ALARM REGISTER
  3411 00003932 66B80B0B            <1> 	MOV	AX,257*CMOS_REG_B ; 
  3412 00003936 E805D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT SETTINGS
  3413 0000393B 247F                <1> 	AND	AL,07FH 	; CLEAR 'SET BIT'
  3414 0000393D 86E0                <1> 	XCHG	AH,AL		; MOVE TO WORK REGISTER
  3415 0000393F E823000000          <1> 	CALL	CMOS_WRITE	; AND START CLOCK UPDATING
  3416 00003944 F8                  <1> 	CLC			; SET CY= 0
  3417 00003945 FB                  <1> 	sti
  3418 00003946 C3                  <1> 	RETn			; RETURN CY=0
  3419                              <1> 
  3420                              <1> 	; 15/03/2015
  3421                              <1> RTC_STA:			; INITIALIZE REAL TIME CLOCK
  3422 00003947 B426                <1> 	mov	ah, 26h
  3423 00003949 B00A                <1> 	mov	al, CMOS_REG_A	; ADDRESS REGISTER A AND LOAD DATA MASK
  3424 0000394B E817000000          <1> 	CALL	CMOS_WRITE	; INITIALIZE STATUS REGISTER A
  3425 00003950 B482                <1> 	mov	ah, 82h
  3426 00003952 B00B                <1> 	mov 	al, CMOS_REG_B	; SET "SET BIT" FOR CLOCK INITIALIZATION
  3427 00003954 E80E000000          <1> 	CALL	CMOS_WRITE	; AND 24 HOUR MODE TO REGISTER B
  3428 00003959 B00C                <1> 	MOV	AL,CMOS_REG_C	; ADDRESS REGISTER C
  3429 0000395B E8E0D1FFFF          <1> 	CALL	CMOS_READ	; READ REGISTER C TO INITIALIZE
  3430 00003960 B00D                <1> 	MOV	AL,CMOS_REG_D	; ADDRESS REGISTER D
  3431                              <1> 	;CALL	CMOS_READ	; READ REGISTER D TO INITIALIZE
  3432                              <1> 	;RETn
  3433                              <1> 	; 12/02/2022
  3434 00003962 E9D9D1FFFF          <1> 	jmp	CMOS_READ
  3435                              <1> 
  3436                              <1> 	; 15/03/2015
  3437                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3438                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3439 00003967 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3440                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3441 00003968 D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3442 0000396A F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3443 0000396B D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3444 0000396D FA                  <1> 	cli			; DISABLE INTERRUPTS
  3445 0000396E E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3446 00003970 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3447 00003972 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3448 00003974 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3449 00003976 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3450 00003978 E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3451 0000397A 90                  <1> 	nop			; I/O DELAY
  3452 0000397B E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3453                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3454 0000397D 9D                  <1> 	popf	
  3455 0000397E C3                  <1> 	RETn
  3456                              <1> 
  3457                              <1> bf_init:
  3458                              <1> 	; 14/08/2015
  3459                              <1> 	; 02/07/2015
  3460                              <1> 	; 01/07/2015
  3461                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3462                              <1> 	; Buffer (pointer) initialization !
  3463                              <1> 	; 
  3464                              <1> 	; 17/07/2013 - 24/07/2013
  3465                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3466                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3467                              <1> 	;
  3468 0000397F BF[1C6F0000]        <1> 	mov	edi, bufp 
  3469 00003984 B8[0C7C0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3470 00003989 29D2                <1> 	sub	edx, edx
  3471 0000398B FECA                <1> 	dec	dl
  3472 0000398D 31C9                <1> 	xor	ecx, ecx
  3473 0000398F 49                  <1> 	dec	ecx
  3474                              <1> bi0:
  3475 00003990 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3476 00003995 AB                  <1> 	stosd
  3477 00003996 89C6                <1> 	mov	esi, eax
  3478 00003998 8916                <1> 	mov	[esi], edx ; 000000FFh
  3479                              <1> 			    ; Not a valid device sign
  3480 0000399A 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3481                              <1> 		      ; Not a valid block number sign 	 	
  3482 0000399D 3D[DC6F0000]        <1> 	cmp	eax, buffer
  3483 000039A2 77EC                <1> 	ja	short bi0
  3484 000039A4 B8[0C7C0000]        <1> 	mov	eax, sb0
  3485 000039A9 AB                  <1> 	stosd
  3486 000039AA B8[147E0000]        <1> 	mov	eax, sb1
  3487 000039AF AB                  <1> 	stosd
  3488 000039B0 89C6                <1> 	mov	esi, eax ; offset sb1
  3489 000039B2 8916                <1> 	mov	[esi], edx ; 000000FFh
  3490                              <1> 			    ; Not a valid device sign
  3491 000039B4 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3492                              <1> 		      ; Not a valid block number sign 	 
  3493                              <1> 	; 14/08/2015
  3494                              <1> 	;call 	rdev_init
  3495                              <1> 	;retn
  3496                              <1> 
  3497                              <1> rdev_init: ; root device, super block buffer initialization
  3498                              <1> 	; 01/02/2022
  3499                              <1> 	; 14/08/2015
  3500                              <1> 	; Retro UNIX 386 v1 feature only !
  3501                              <1> 	;
  3502                              <1> 	; NOTE: Disk partitions (file systems), logical
  3503                              <1> 	; drive initialization, partition's start sector etc.
  3504                              <1> 	; will be coded here, later in 'ldrv_init'	
  3505                              <1> 
  3506 000039B7 0FB605[8A660000]    <1> 	movzx	eax, byte [boot_drv]
  3507                              <1> rdi_0:
  3508 000039BE 3C80                <1> 	cmp	al, 80h
  3509 000039C0 7202                <1> 	jb	short rdi_1
  3510 000039C2 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3511                              <1> rdi_1:
  3512 000039C4 A2[426F0000]        <1> 	mov	[rdev], al
  3513 000039C9 BB[0C7C0000]        <1>         mov	ebx, sb0 ; super block buffer
  3514 000039CE 8903                <1> 	mov 	[ebx], eax
  3515 000039D0 B001                <1> 	mov	al, 1 ; eax = 1
  3516 000039D2 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3517                              <1> 	;call 	diskio
  3518                              <1> 	;retn
  3519                              <1> 	; 01/02/2022
  3520 000039D5 E92D250000          <1> 	jmp	diskio
  3521                              <1> 
  3522                              <1> ; 23/10/2015
  3523                              <1> com1_irq4:
  3524 000039DA [E2390000]          <1> 	dd dummy_retn
  3525                              <1> com2_irq3:
  3526 000039DE [E2390000]          <1> 	dd dummy_retn
  3527                              <1> 
  3528                              <1> dummy_retn:
  3529 000039E2 C3                  <1> 	retn
  2047                                  %include 'u1.s'        ; 10/05/2015
  2048                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2049                              <1> ; Last Modification: 27/02/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 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2060                              <1> ;
  2061                              <1> ; ****************************************************************************
  2062                              <1> ; 23/11/2015
  2063                              <1> 
  2064                              <1> unkni: ; / used for all system calls
  2065                              <1> sysent: ; < enter to system call >
  2066                              <1> 	; 27/02/2022
  2067                              <1> 	; 01/02/2022
  2068                              <1> 	; 19/10/2015
  2069                              <1> 	; 21/09/2015
  2070                              <1> 	; 01/07/2015
  2071                              <1> 	; 19/05/2015
  2072                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2073                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2074                              <1> 	;
  2075                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2076                              <1> 	; The trap type is determined and an indirect jump is made to 
  2077                              <1> 	; the appropriate system call handler. If there is a trap inside
  2078                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2079                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2080                              <1> 	; instructor is decoded to get the the system code part (see
  2081                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2082                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2083                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2084                              <1> 	; is called. If the call is legitimate control passes to the
  2085                              <1> 	; appropriate system routine.
  2086                              <1> 	;
  2087                              <1> 	; Calling sequence:
  2088                              <1> 	;	Through a trap caused by any sys call outside the system.
  2089                              <1> 	; Arguments:
  2090                              <1> 	;	Arguments of particular system call.	
  2091                              <1> 	; ...............................................................
  2092                              <1> 	;	
  2093                              <1> 	; Retro UNIX 8086 v1 modification: 
  2094                              <1> 	;       System call number is in EAX register.
  2095                              <1> 	;
  2096                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2097                              <1> 	;	registers depending of function details.
  2098                              <1>   	;
  2099                              <1> 	; 16/04/2015
  2100 000039E3 368925[546F0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2101                              <1> 	; save user registers
  2102 000039EA 1E                  <1> 	push	ds
  2103 000039EB 06                  <1> 	push	es
  2104 000039EC 0FA0                <1> 	push	fs
  2105 000039EE 0FA8                <1> 	push	gs
  2106 000039F0 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2107                              <1> 	;
  2108                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2109                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2110                              <1> 	;	for saving/restoring user registers.)
  2111                              <1> 	;
  2112 000039F1 50                  <1> 	push	eax ; 01/07/2015
  2113 000039F2 66B81000            <1> 	mov     ax, KDATA
  2114 000039F6 8ED8                <1>         mov     ds, ax
  2115 000039F8 8EC0                <1>         mov     es, ax
  2116 000039FA 8EE0                <1>         mov     fs, ax
  2117 000039FC 8EE8                <1>         mov     gs, ax
  2118 000039FE A1[986B0000]        <1> 	mov	eax, [k_page_dir]
  2119 00003A03 0F22D8              <1> 	mov	cr3, eax
  2120 00003A06 58                  <1> 	pop	eax ; 01/07/2015
  2121                              <1> 	; 19/10/2015
  2122 00003A07 FC                  <1> 	cld
  2123                              <1> 	;
  2124 00003A08 FE05[536F0000]      <1> 	inc	byte [sysflg]
  2125                              <1> 		; incb sysflg / indicate a system routine is in progress
  2126 00003A0E FB                  <1>         sti 	; 18/01/2014
  2127                              <1> 	;jnz	panic ; 24/05/2013
  2128                              <1> 		; beq 1f
  2129                              <1> 		; jmp panic ; / called if trap inside system
  2130                              <1> 	; 01/02/2022
  2131 00003A0F 7405                <1> 	jz	short sysent_1
  2132 00003A11 E984F9FFFF          <1> 	jmp	panic
  2133                              <1> sysent_1:
  2134                              <1> ;1:	; 16/04/2015
  2135 00003A16 A3[5C6F0000]        <1> 	mov	[u.r0], eax
  2136 00003A1B 8925[586F0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2137                              <1> 	;
  2138                              <1> 		; mov $s.syst+2,clockp
  2139                              <1> 		; mov r0,-(sp) / save user registers 
  2140                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2141                              <1> 			   ; / in u.r0
  2142                              <1> 		; mov r1,-(sp)
  2143                              <1> 		; mov r2,-(sp)
  2144                              <1> 		; mov r3,-(sp)
  2145                              <1> 		; mov r4,-(sp)
  2146                              <1> 		; mov r5,-(sp)
  2147                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2148                              <1> 		             ; / arithmetic unit
  2149                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2150                              <1> 		             ; / extended arithmetic unit
  2151                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2152                              <1> 		             ; / arithmetic unit
  2153                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2154                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2155                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2156                              <1> 		; sub $sys,r0 / get xxx code
  2157 00003A21 C1E002              <1> 	shl	eax, 2
  2158                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2159 00003A24 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2160                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2161                              <1> 	;jnb	short badsys
  2162                              <1> 		; bhis badsys / yes, bad system call
  2163                              <1> 	; 27/02/2022
  2164 00003A29 7205                <1> 	jb	short _2
  2165 00003A2B E954010000          <1> 	jmp	badsys
  2166                              <1> _2:
  2167                              <1> 	; 27/02/2022
  2168                              <1> 	;cmc
  2169                              <1> 	;pushf	
  2170                              <1> 	;push	eax
  2171 00003A30 8B2D[546F0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2172                              <1> 	;mov	al, 0FEh ; 11111110b
  2173                              <1> 	;;adc	al, 0 ; al = al + cf
  2174                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2175 00003A36 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2176                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2177                              <1> 				 ; / and clear carry bit
  2178                              <1> 	;pop	ebp ; eax
  2179 00003A3A 89C5                <1> 	mov	ebp, eax
  2180                              <1> 	;popf
  2181                              <1>         ;;jc	badsys
  2182                              <1> 	; 27/02/2022
  2183                              <1> 	;jnc	short _3
  2184                              <1> 	;jmp	badsys
  2185                              <1> ;_3:
  2186 00003A3C A1[5C6F0000]        <1> 	mov	eax, [u.r0]
  2187                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2188 00003A41 FFA5[473A0000]      <1> 	jmp	dword [ebp+syscalls]
  2189                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2190                              <1> 		            ; / to proper system routine.
  2191                              <1> syscalls: ; 1:
  2192                              <1> 	; 21/09/2015
  2193                              <1> 	; 01/07/2015
  2194                              <1> 	; 16/04/2015 (32 bit address modification) 
  2195 00003A47 [4E3B0000]          <1> 	dd sysrele	; / 0
  2196 00003A4B [F63B0000]          <1> 	dd sysexit 	; / 1
  2197 00003A4F [213D0000]          <1> 	dd sysfork 	; / 2
  2198 00003A53 [273E0000]          <1> 	dd sysread 	; / 3
  2199 00003A57 [3A3E0000]          <1> 	dd syswrite 	; / 4
  2200 00003A5B [A33E0000]          <1> 	dd sysopen 	; / 5
  2201 00003A5F [D23F0000]          <1> 	dd sysclose 	; / 6
  2202 00003A63 [9C3C0000]          <1> 	dd syswait 	; / 7
  2203 00003A67 [4F3F0000]          <1> 	dd syscreat 	; / 8
  2204 00003A6B [84430000]          <1> 	dd syslink 	; / 9
  2205 00003A6F [40440000]          <1> 	dd sysunlink 	; / 10
  2206 00003A73 [07450000]          <1> 	dd sysexec 	; / 11
  2207 00003A77 [904B0000]          <1> 	dd syschdir 	; / 12
  2208 00003A7B [754C0000]          <1> 	dd systime 	; / 13
  2209 00003A7F [8B3F0000]          <1> 	dd sysmkdir 	; / 14
  2210 00003A83 [E24B0000]          <1> 	dd syschmod 	; / 15
  2211 00003A87 [454C0000]          <1> 	dd syschown 	; / 16
  2212 00003A8B [A84C0000]          <1> 	dd sysbreak 	; / 17
  2213 00003A8F [C8480000]          <1> 	dd sysstat 	; / 18
  2214 00003A93 [784D0000]          <1> 	dd sysseek 	; / 19
  2215 00003A97 [8A4D0000]          <1> 	dd systell 	; / 20
  2216 00003A9B [49580000]          <1> 	dd sysmount 	; / 21
  2217 00003A9F [34590000]          <1> 	dd sysumount 	; / 22
  2218 00003AA3 [064E0000]          <1> 	dd syssetuid 	; / 23
  2219 00003AA7 [374E0000]          <1> 	dd sysgetuid 	; / 24
  2220 00003AAB [844C0000]          <1> 	dd sysstime 	; / 25
  2221 00003AAF [FA4D0000]          <1> 	dd sysquit 	; / 26
  2222 00003AB3 [EE4D0000]          <1> 	dd sysintr 	; / 27
  2223 00003AB7 [A5480000]          <1> 	dd sysfstat 	; / 28
  2224 00003ABB [EA3F0000]          <1> 	dd sysemt 	; / 29
  2225 00003ABF [32400000]          <1> 	dd sysmdate 	; / 30
  2226 00003AC3 [8C400000]          <1> 	dd sysstty 	; / 31
  2227 00003AC7 [77420000]          <1> 	dd sysgtty 	; / 32
  2228 00003ACB [2D400000]          <1> 	dd sysilgins 	; / 33
  2229 00003ACF [C0610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2230                              <1> 			     ; 11/06/2014
  2231 00003AD3 [D7610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2232                              <1> 			     ; 01/07/2015
  2233 00003AD7 [AF620000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2234                              <1> 			     ; 21/09/2015 - get last error number
  2235                              <1> end_of_syscalls:
  2236                              <1> 
  2237                              <1> error:
  2238                              <1> 	; 17/09/2015
  2239                              <1> 	; 03/09/2015
  2240                              <1> 	; 01/09/2015
  2241                              <1> 	; 09/06/2015
  2242                              <1> 	; 13/05/2015
  2243                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2244                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2245                              <1> 	;
  2246                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2247                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2248                              <1> 	;
  2249                              <1> 	; INPUTS -> none
  2250                              <1> 	; OUTPUTS ->
  2251                              <1> 	;	processor status - carry (c) bit is set (means error)
  2252                              <1> 	;
  2253                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2254                              <1> 	; 	      Because, jumps to error procedure
  2255                              <1> 	;	      disrupts push-pop nesting balance)
  2256                              <1> 	;
  2257 00003ADB 8B2D[546F0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2258 00003AE1 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2259                              <1> 				 ; (system call will return with cf = 1)
  2260                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2261                              <1> 		               ; / users stack
  2262                              <1> 	; 17/09/2015
  2263 00003AE5 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2264                              <1> 				 ; for saving/restoring user registers	
  2265                              <1> 	;cmp	ebp, [u.usp]
  2266                              <1> 	;je	short err0	
  2267 00003AE8 892D[586F0000]      <1> 	mov	[u.usp], ebp
  2268                              <1> ;err0:
  2269                              <1> 	; 01/09/2015
  2270 00003AEE 8B25[586F0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2271                              <1> 				    ; 10/04/2013
  2272                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2273                              <1> 				    ; related procedures will jump to 'error'
  2274                              <1> 				    ; procedure directly without returning to 
  2275                              <1> 				    ; the caller procedure. So, stack pointer
  2276                              <1>                                     ; must be restored here.)
  2277                              <1> 	; 13/05/2015
  2278                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2279                              <1> 	;	'get last error' system call later. 	
  2280                              <1> 
  2281                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2282 00003AF4 C605[BD6F0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2283                              <1> 
  2284                              <1> sysret: ; < return from system call>
  2285                              <1> 	; 01/02/2022
  2286                              <1> 	; 10/09/2015
  2287                              <1> 	; 29/07/2015
  2288                              <1> 	; 25/06/2015
  2289                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2290                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2291                              <1> 	;
  2292                              <1> 	; 'sysret' first checks to see if process is about to be 
  2293                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2294                              <1> 	; If not, following happens:	 
  2295                              <1> 	; 	1) The user's stack pointer is restored.
  2296                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2297                              <1> 	;	   i-node has been modified. If it has, it is written out
  2298                              <1> 	;	   via 'ppoke'.
  2299                              <1> 	;	3) If the super block has been modified, it is written out
  2300                              <1> 	;	   via 'ppoke'.				
  2301                              <1> 	;	4) If the dismountable file system's super block has been
  2302                              <1> 	;	   modified, it is written out to the specified device
  2303                              <1> 	;	   via 'ppoke'.
  2304                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2305                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2306                              <1> 	;	   another user a chance to run.
  2307                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2308                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2309                              <1> 	;
  2310                              <1> 	; Calling sequence:
  2311                              <1> 	;	jump table or 'br sysret'
  2312                              <1> 	; Arguments: 
  2313                              <1> 	;	-	
  2314                              <1> 	; ...............................................................
  2315                              <1> 	;	
  2316                              <1> 	; ((AX=r1 for 'iget' input))
  2317                              <1> 	;	
  2318                              <1> 	;xor	ax, ax ; 04/05/2013
  2319                              <1> 	; 01/02/2022
  2320 00003AFB 31C0                <1> 	xor	eax, eax
  2321                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2322 00003AFD FEC0                <1> 	inc	al ; 04/05/2013
  2323 00003AFF 3805[A46F0000]      <1> 	cmp	[u.bsys], al ; 1
  2324                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2325                              <1>         ;jnb	sysexit ; 04/05/2013
  2326                              <1> 		; bne sysexit / of an error? yes, go to sysexit
  2327                              <1> 	; 01/02/2022
  2328 00003B05 7205                <1> 	jb	short sysret_2
  2329 00003B07 E9EA000000          <1> 	jmp	sysexit
  2330                              <1> sysret_2:
  2331                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2332                              <1> 		; mov u.sp,sp / no point stack to users stack
  2333 00003B0C FEC8                <1> 	dec 	al ; mov ax, 0
  2334                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2335 00003B0E E8DE160000          <1> 	call	iget
  2336                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2337                              <1> 		            ; / it is written out
  2338 00003B13 6631C0              <1> 	xor 	ax, ax ; 0
  2339 00003B16 3805[516F0000]      <1> 	cmp	[smod], al ; 0
  2340                              <1> 		; tstb	smod / has the super block been modified
  2341 00003B1C 7614                <1> 	jna	short sysret1
  2342                              <1> 		; beq	1f / no, 1f
  2343 00003B1E A2[516F0000]        <1> 	mov	[smod], al ; 0
  2344                              <1> 		; clrb smod / yes, clear smod
  2345 00003B23 BB[0C7C0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2346 00003B28 66810B0002          <1>    	or	word [ebx], 200h ;;
  2347                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2348                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2349                              <1> 		      	      ; / output
  2350                              <1> 	; AX = 0
  2351 00003B2D E8BD220000          <1> 	call 	poke ; 07/08/2013
  2352                              <1> 	;call	ppoke
  2353                              <1> 	; AX = 0
  2354                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2355                              <1> sysret1: ;1:
  2356 00003B32 3805[526F0000]      <1> 	cmp	[mmod], al ; 0
  2357                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2358                              <1> 		           ; / system
  2359 00003B38 7614                <1> 	jna	short sysrel0
  2360                              <1> 		; beq 1f / been modified?  no, 1f
  2361 00003B3A A2[526F0000]        <1> 	mov	[mmod], al ; 0	
  2362                              <1> 		; clrb	mmod / yes, clear mmod
  2363                              <1>         ;mov    ax, [mntd]
  2364                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2365 00003B3F BB[147E0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2366                              <1>         ;;mov	[ebx], al
  2367                              <1> 	;mov    [sb1], al
  2368                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2369 00003B44 66810B0002          <1> 	or	word [ebx], 200h
  2370                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2371                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2372 00003B49 E8A1220000          <1> 	call	poke ; 07/08/2013
  2373                              <1> 	;call	ppoke 
  2374                              <1> 		; jsr r0,ppoke / write it out to its device
  2375                              <1>         ;xor    al, al ; 26/04/2013       
  2376                              <1> ;1:
  2377                              <1> 		; tstb uquant / is the time quantum 0?
  2378                              <1> 		; bne 1f / no, don't swap it out
  2379                              <1> 
  2380                              <1> sysrele: ; < release >
  2381                              <1> 	; 14/10/2015
  2382                              <1> 	; 01/09/2015
  2383                              <1> 	; 24/07/2015
  2384                              <1> 	; 14/05/2015
  2385                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2386                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2387                              <1> 	;
  2388                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2389                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2390                              <1> 	; turns off the system flag. It then checked to see if there is
  2391                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2392                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2393                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2394                              <1> 	; the user, a rti is made.
  2395                              <1> 	;
  2396                              <1> 	; Calling sequence:
  2397                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2398                              <1> 	; Arguments:
  2399                              <1> 	;	-	
  2400                              <1> 	; ...............................................................
  2401                              <1> 	;	
  2402                              <1> 	; 23/02/2014 (swapret)
  2403                              <1> 	; 22/09/2013
  2404                              <1> sysrel0: ;1:
  2405 00003B4E 803D[986F0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2406                              <1> 		; tstb uquant / is the time quantum 0?
  2407 00003B55 7705                <1>         ja      short swapret
  2408                              <1> 		; bne 1f / no, don't swap it out
  2409                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2410 00003B57 E82B130000          <1> 	call	tswap
  2411                              <1> 		; jsr r0,tswap / yes, swap it out
  2412                              <1> ;
  2413                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2414                              <1> swapret: ;1:
  2415                              <1> 	; 10/09/2015
  2416                              <1> 	; 01/09/2015
  2417                              <1> 	; 14/05/2015
  2418                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2419                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2420                              <1> 	; cli
  2421                              <1> 	; 24/07/2015
  2422                              <1> 	;
  2423                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2424                              <1> 	;; mov	esp, [u.usp]
  2425                              <1> 
  2426                              <1> 	; 22/09/2013
  2427 00003B5C E8FD140000          <1> 	call	isintr
  2428                              <1> 	; 20/10/2013
  2429 00003B61 7405                <1> 	jz	short sysrel1
  2430 00003B63 E877000000          <1> 	call	intract
  2431                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2432                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2433                              <1> 		               ; / action
  2434                              <1> sysrel1:
  2435 00003B68 FA                  <1> 	cli ; 14/10/2015
  2436 00003B69 FE0D[536F0000]      <1> 	dec	byte [sysflg]
  2437                              <1> 		; decb sysflg / turn system flag off
  2438 00003B6F A1[AF6F0000]        <1> 	mov     eax, [u.pgdir]
  2439 00003B74 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2440                              <1> 			  ; (others are different than kernel page tables) 
  2441                              <1> 	; 10/09/2015
  2442 00003B77 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2443                              <1> 		; mov (sp)+,sc / restore user registers
  2444                              <1> 		; mov (sp)+,mq
  2445                              <1> 		; mov (sp)+,ac
  2446                              <1> 		; mov (sp)+,r5
  2447                              <1> 		; mov (sp)+,r4
  2448                              <1> 		; mov (sp)+,r3
  2449                              <1> 		; mov (sp)+,r2
  2450                              <1> 	;
  2451 00003B78 A1[5C6F0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2452 00003B7D 0FA9                <1> 	pop	gs
  2453 00003B7F 0FA1                <1> 	pop	fs
  2454 00003B81 07                  <1> 	pop	es
  2455 00003B82 1F                  <1> 	pop	ds
  2456 00003B83 CF                  <1> 	iretd	
  2457                              <1> 		; rti / no, return from interrupt
  2458                              <1> 
  2459                              <1> badsys:
  2460                              <1> 	; 27/02/2022
  2461                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2462                              <1> 	; (Major Modification: 'core' dumping procedure in
  2463                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2464                              <1> 	;	has been changed to print 'Invalid System Call !'
  2465                              <1> 	;	message on the user's console tty.)
  2466                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2467                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2468                              <1> 	; (EAX = Function number)  
  2469                              <1> 	;
  2470 00003B84 FE05[A46F0000]      <1> 	inc	byte [u.bsys]
  2471                              <1> 	;
  2472 00003B8A 8B1D[546F0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2473 00003B90 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2474 00003B92 E879DBFFFF          <1> 	call	dwordtohex
  2475 00003B97 8915[F2680000]      <1> 	mov	[bsys_msg_eip], edx
  2476 00003B9D A3[F6680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2477 00003BA2 A1[5C6F0000]        <1> 	mov	eax, [u.r0]
  2478 00003BA7 E864DBFFFF          <1> 	call	dwordtohex
  2479 00003BAC 8915[E2680000]      <1> 	mov	[bsys_msg_eax], edx
  2480 00003BB2 A3[E6680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2481                              <1> 	; 27/02/2022
  2482                              <1> 	;xor	eax, eax
  2483                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2484                              <1> 	;mov	ebx, [u.fofp]
  2485                              <1> 	;mov	[ebx], eax
  2486                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2487                              <1> 	;inc	eax
  2488                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2489                              <1> 		; writei
  2490                              <1> 		; INPUTS ->
  2491                              <1> 		;    r1 - inode number
  2492                              <1> 		;    u.count - byte count to be written
  2493                              <1> 		;    u.base - points to user buffer
  2494                              <1> 		;    u.fofp - points to word with current file offset
  2495                              <1> 		; OUTPUTS ->
  2496                              <1> 		;    u.count - cleared
  2497                              <1> 		;    u.nread - accumulates total bytes passed back	
  2498                              <1> 		;
  2499                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2500                              <1> 	;call	writei
  2501                              <1> 	;;mov	eax, 1
  2502                              <1> 	;jmp	sysexit
  2503                              <1> 
  2504                              <1> 	; 27/02/2022
  2505 00003BB7 BE[C3680000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2506 00003BBC 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2507 00003BC3 8A83[B76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2508 00003BC9 C605[C76B0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2509 00003BD0 A2[AA6F0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2510 00003BD5 E8BA260000          <1> 	call	print_cmsg
  2511                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2512 00003BDA E9FCFEFFFF          <1> 	jmp	error
  2513                              <1> 
  2514                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2515                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2516                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2517                              <1> 		; br 1f / error
  2518                              <1> 		; neg r1 / negate the i-number to open the core image file
  2519                              <1> 		       ; / for writing
  2520                              <1> 		; jsr r0,iopen / open the core image file
  2521                              <1> 		; jsr r0,itrunc / free all associated blocks
  2522                              <1> 		; br 2f
  2523                              <1> ;1:
  2524                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2525                              <1> 		; jsr r0,maknod / make an i-node
  2526                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2527                              <1> ;2:
  2528                              <1> 		; mov $core,u.base / move address core to u.base
  2529                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2530                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2531                              <1> 		; clr u.off / clear user offset
  2532                              <1> 		; jsr r0,writei / write out the core image to the user
  2533                              <1> 		; mov $user,u.base / pt. u.base to user
  2534                              <1> 		; mov $64.,u.count / u.count = 64
  2535                              <1> 		; jsr r0,writei / write out all the user parameters
  2536                              <1> 		; neg r1 / make i-number positive
  2537                              <1> 		; jsr r0,iclose / close the core image file
  2538                              <1> 		; br sysexit /
  2539                              <1> ;3:
  2540                              <1> 		; <core\0\0>
  2541                              <1> 
  2542                              <1> intract: ; / interrupt action
  2543                              <1> 	; 14/10/2015
  2544                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2545                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2546                              <1> 	;
  2547                              <1> 	; Retro UNIX 8086 v1 modification !
  2548                              <1> 	; (Process/task switching and quit routine by using
  2549                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2550                              <1> 	;
  2551                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2552                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2553                              <1> 	;		'intract' will jump to 'sysexit'.
  2554                              <1> 	;	    Intract will return to the caller 
  2555                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2556                              <1> 	; 14/10/2015
  2557 00003BDF FB                  <1> 	sti
  2558                              <1> 	; 07/12/2013	
  2559 00003BE0 66FF05[9C6F0000]    <1> 	inc 	word [u.quit]
  2560 00003BE7 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2561 00003BE9 66FF0D[9C6F0000]    <1> 	dec	word [u.quit]
  2562                              <1> 	; 16/04/2015
  2563 00003BF0 C3                  <1> 	retn
  2564                              <1> intrct0:	
  2565 00003BF1 58                  <1> 	pop	eax ; call intract -> retn
  2566                              <1> 	;
  2567 00003BF2 31C0                <1> 	xor 	eax, eax
  2568 00003BF4 FEC0                <1> 	inc	al  ; mov ax, 1
  2569                              <1> ;;;
  2570                              <1> 	; UNIX v1 original 'intract' routine... 
  2571                              <1> 	; / interrupt action
  2572                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2573                              <1> 		; bne 1f / no, 1f
  2574                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2575                              <1> 	; 1: / now in user area
  2576                              <1> 		; mov r1,-(sp) / save r1
  2577                              <1> 		; mov u.ttyp,r1 
  2578                              <1> 			; / pointer to tty buffer in control-to r1
  2579                              <1> 		; cmpb 6(r1),$177
  2580                              <1> 			; / is the interrupt char equal to "del"
  2581                              <1> 		; beq 1f / yes, 1f
  2582                              <1> 		; clrb 6(r1) 
  2583                              <1> 		        ; / no, clear the byte 
  2584                              <1> 			; / (must be a quit character)
  2585                              <1> 		; mov (sp)+,r1 / restore r1
  2586                              <1> 		; clr u.quit / clear quit flag
  2587                              <1> 		; bis $20,2(sp) 
  2588                              <1> 		    	; / set trace for quit (sets t bit of 
  2589                              <1> 			; / ps-trace trap)
  2590                              <1> 		; rti   ;  / return from interrupt
  2591                              <1> 	; 1: / interrupt char = del
  2592                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2593                              <1> 			   ; / in the buffer
  2594                              <1> 		; mov (sp)+,r1 / restore r1
  2595                              <1> 		; cmp u.intr,$core / should control be 
  2596                              <1> 				; / transferred to loc core?
  2597                              <1> 		; blo 1f
  2598                              <1> 		; jmp *u.intr / user to do rti yes, 
  2599                              <1> 				; / transfer to loc core
  2600                              <1> 	; 1:
  2601                              <1> 		; sys 1 / exit
  2602                              <1> 
  2603                              <1> sysexit: ; <terminate process>
  2604                              <1> 	; 01/02/2022
  2605                              <1> 	; 01/09/2015
  2606                              <1> 	; 31/08/2015
  2607                              <1> 	; 14/05/2015
  2608                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2609                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2610                              <1> 	;
  2611                              <1> 	; 'sysexit' terminates a process. First each file that
  2612                              <1> 	; the process has opened is closed by 'flose'. The process
  2613                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2614                              <1> 	; searched to find children of the dying process. If any of
  2615                              <1> 	; children are zombies (died by not waited for), they are
  2616                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2617                              <1> 	; dying process's parent. When the parent is found, it is
  2618                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2619                              <1> 	; one of these, the dying process just dies. If it is waiting
  2620                              <1> 	; for a child process to die, it notified that it doesn't 
  2621                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2622                              <1> 	; (waiting to active). It is awakened and put on runq by
  2623                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2624                              <1> 	; it will never be run again but stays around until a 'wait'
  2625                              <1> 	; is completed by it's parent process. If the parent is not
  2626                              <1> 	; found, process just dies. This means 'swap' is called with
  2627                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2628                              <1> 	; to write out the process and 'rswap' reads the new process
  2629                              <1> 	; over the one that dies..i.e., the dying process is 
  2630                              <1> 	; overwritten and destroyed.	
  2631                              <1>  	;
  2632                              <1> 	; Calling sequence:
  2633                              <1> 	;	sysexit or conditional branch.
  2634                              <1> 	; Arguments:
  2635                              <1> 	;	-	
  2636                              <1> 	; ...............................................................
  2637                              <1> 	;	
  2638                              <1> 	; Retro UNIX 8086 v1 modification: 
  2639                              <1> 	;       System call number (=1) is in EAX register.
  2640                              <1> 	;
  2641                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2642                              <1> 	;       registers depending of function details.
  2643                              <1> 	;
  2644                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2645                              <1> 	;
  2646                              <1> ; / terminate process
  2647                              <1> 	; AX = 1
  2648                              <1> 	;dec 	ax ; 0
  2649                              <1> 	; 01/02/2022
  2650 00003BF6 48                  <1> 	dec	eax ; 0
  2651 00003BF7 66A3[9A6F0000]      <1> 	mov	[u.intr], ax ; 0
  2652                              <1> 		; clr u.intr / clear interrupt control word
  2653                              <1> 		; clr r1 / clear r1
  2654                              <1> 	; AX = 0
  2655                              <1> sysexit_1: ; 1:
  2656                              <1> 	; AX = File descriptor
  2657                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2658                              <1> 		; / Search the whole list
  2659 00003BFD E8640D0000          <1> 	call	fclose
  2660                              <1> 		; jsr r0,fclose / close all files the process opened
  2661                              <1> 	;; ignore error return
  2662                              <1> 		; br .+2 / ignore error return
  2663                              <1> 	;inc	ax
  2664 00003C02 FEC0                <1> 	inc	al
  2665                              <1> 		; inc r1 / increment file descriptor
  2666                              <1> 	;cmp	ax, 10
  2667 00003C04 3C0A                <1> 	cmp	al, 10
  2668                              <1> 		; cmp r1,$10. / end of u.fp list?
  2669 00003C06 72F5                <1> 	jb	short sysexit_1
  2670                              <1> 		; blt 1b / no, go back
  2671 00003C08 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2672                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2673 00003C0F 88A3[D76C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2674                              <1> 		; clrb p.stat-1(r1) / free the process
  2675                              <1> 	;shl	bx, 1
  2676 00003C15 D0E3                <1> 	shl	bl, 1
  2677                              <1> 		; asl r1 / use r1 for index into the below tables
  2678 00003C17 668B8B[766C0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2679                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2680 00003C1E 668B93[966C0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2681                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2682                              <1> 	;xor 	bx, bx ; 0
  2683 00003C25 30DB                <1> 	xor	bl, bl ; 0
  2684                              <1> 		; clr r2
  2685 00003C27 31F6                <1> 	xor	esi, esi ; 0
  2686                              <1> 		; clr r5 / initialize reg
  2687                              <1> sysexit_2: ; 1:
  2688                              <1> 	        ; / find children of this dying process, 
  2689                              <1> 		; / if they are zombies, free them
  2690                              <1> 	;add	bx, 2
  2691 00003C29 80C302              <1> 	add	bl, 2
  2692                              <1> 		; add $2,r2 / search parent process table 
  2693                              <1> 		          ; / for dying process's name
  2694 00003C2C 66398B[966C0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2695                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2696 00003C33 7513                <1> 	jne	short sysexit_4
  2697                              <1> 		; bne 3f / no
  2698                              <1> 	;shr	bx, 1
  2699 00003C35 D0EB                <1> 	shr	bl, 1
  2700                              <1> 		; asr r2 / yes, it is a parent
  2701 00003C37 80BB[D76C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2702                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2703                              <1> 				     ; / dying process a zombie
  2704 00003C3E 7506                <1> 	jne	short sysexit_3 
  2705                              <1> 		; bne 2f / no
  2706 00003C40 88A3[D76C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2707                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2708                              <1> sysexit_3: ; 2:
  2709                              <1> 	;shr	bx, 1
  2710 00003C46 D0E3                <1> 	shl	bl, 1
  2711                              <1> 		; asl r2
  2712                              <1> sysexit_4: ; 3:
  2713                              <1> 		; / search the process name table 
  2714                              <1> 		; / for the dying process's parent
  2715 00003C48 663993[766C0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2716                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2717 00003C4F 7502                <1> 	jne	short sysexit_5
  2718                              <1> 		; bne 3f / no
  2719 00003C51 89DE                <1> 	mov	esi, ebx
  2720                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2721                              <1> 		          ; / process # x2) in r5
  2722                              <1> sysexit_5: ; 3:
  2723                              <1> 	;cmp	bx, nproc + nproc
  2724 00003C53 80FB20              <1> 	cmp	bl, nproc + nproc
  2725                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2726 00003C56 72D1                <1> 	jb	short sysexit_2
  2727                              <1> 		; blt 1b / no, go back
  2728                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2729 00003C58 21F6                <1> 	and	esi, esi ; r5=r1
  2730 00003C5A 7431                <1> 	jz	short sysexit_6
  2731                              <1> 		; beq 2f / no parent has been found. 
  2732                              <1> 		       ; / The process just dies
  2733 00003C5C 66D1EE              <1> 	shr	si, 1
  2734                              <1> 		; asr r1 / set up index to p.stat
  2735 00003C5F 8A86[D76C0000]      <1> 	mov	al, [esi+p.stat-1]
  2736                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2737 00003C65 20C0                <1> 	and	al, al
  2738 00003C67 7424                <1> 	jz	short sysexit_6
  2739                              <1> 		; beq 2f / if its been freed, 2f
  2740 00003C69 3C03                <1> 	cmp	al, 3
  2741                              <1> 		; cmp r2,$3 / is parent a zombie?
  2742 00003C6B 7420                <1> 	je	short sysexit_6
  2743                              <1> 		; beq 2f / yes, 2f
  2744                              <1> 	; BH = 0
  2745 00003C6D 8A1D[A56F0000]      <1> 	mov	bl, [u.uno]
  2746                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2747 00003C73 C683[D76C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2748                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2749                              <1> 	; 05/02/2014
  2750 00003C7A 3C01                <1> 	cmp	al, 1 ; SRUN
  2751 00003C7C 740F                <1> 	je	short sysexit_6
  2752                              <1> 	;cmp	al, 2
  2753                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2754                              <1> 			  ; / this child to die
  2755                              <1> 	;jne	short sysexit_6	
  2756                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2757                              <1> 	; 05/02/2014
  2758                              <1> 	; p.stat = 2 --> waiting
  2759                              <1> 	; p.stat = 4 --> sleeping
  2760 00003C7E C686[D76C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2761                              <1> 	;dec	byte [esi+p.stat-1]
  2762                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2763 00003C85 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2764                              <1> 	; 
  2765                              <1> 	;mov	ebx, runq + 4
  2766                              <1> 		; mov $runq+4,r2 / on the runq
  2767 00003C88 E8D1120000          <1> 	call	putlu
  2768                              <1> 		; jsr r0, putlu
  2769                              <1> sysexit_6: ; 2:
  2770                              <1> 	; 31/08/2015
  2771                              <1> 		; / the process dies
  2772 00003C8D C605[A56F0000]00    <1> 	mov	byte [u.uno], 0
  2773                              <1> 		; clrb u.uno / put zero as the process number, 
  2774                              <1> 	           ; / so "swap" will
  2775 00003C94 E8F8110000          <1> 	call	swap
  2776                              <1> 		; jsr r0,swap / overwrite process with another process
  2777                              <1> hlt_sys:
  2778                              <1> 	;sti ; 18/01/2014
  2779                              <1> hlts0:
  2780 00003C99 F4                  <1> 	hlt
  2781 00003C9A EBFD                <1> 	jmp	short hlts0
  2782                              <1> 		; 0 / and thereby kill it; halt?
  2783                              <1> 
  2784                              <1> 
  2785                              <1> syswait: ; < wait for a processs to die >
  2786                              <1> 	; 12/02/2022
  2787                              <1> 	; 01/02/2022
  2788                              <1> 	; 17/09/2015
  2789                              <1> 	; 02/09/2015
  2790                              <1> 	; 01/09/2015
  2791                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2792                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2793                              <1> 	;
  2794                              <1> 	; 'syswait' waits for a process die. 
  2795                              <1> 	; It works in following way:
  2796                              <1> 	;    1) From the parent process number, the parent's 
  2797                              <1> 	; 	process name is found. The p.ppid table of parent
  2798                              <1> 	;	names is then searched for this process name.
  2799                              <1> 	;	If a match occurs, r2 contains child's process
  2800                              <1> 	;	number. The child status is checked to see if it is
  2801                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2802                              <1> 	;	If it is, the child process is freed and it's name
  2803                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2804                              <1> 	;	If the child is not a zombie, nothing happens and
  2805                              <1> 	;	the search goes on through the p.ppid table until
  2806                              <1> 	;	all processes are checked or a zombie is found.
  2807                              <1> 	;    2) If no zombies are found, a check is made to see if
  2808                              <1> 	;	there are any children at all. If there are none,
  2809                              <1> 	;	an error return is made. If there are, the parent's
  2810                              <1> 	;	status is set to 2 (waiting for child to die),
  2811                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2812                              <1> 	;	is made to wait on the next process.
  2813                              <1> 	;
  2814                              <1> 	; Calling sequence:
  2815                              <1> 	;	?
  2816                              <1> 	; Arguments:
  2817                              <1> 	;	-
  2818                              <1> 	; Inputs: - 
  2819                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2820                              <1> 	; ...............................................................
  2821                              <1> 	;				
  2822                              <1> 	
  2823                              <1> ; / wait for a process to die
  2824                              <1> 
  2825                              <1> syswait_0:
  2826 00003C9C 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2827                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2828 00003CA3 D0E3                <1> 	shl	bl, 1
  2829                              <1> 	;shl	bx, 1
  2830                              <1> 		; asl r1 / x2 to get index into p.pid table
  2831 00003CA5 668B83[766C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2832                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2833 00003CAC 31F6                <1> 	xor	esi, esi
  2834                              <1> 		; clr r2
  2835 00003CAE 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2836                              <1> 	;xor 	cl, cl
  2837                              <1> 		; clr r3 / initialize reg 3
  2838                              <1> syswait_1: ; 1:
  2839                              <1> 	; 12/02/2022
  2840 00003CB0 46                  <1> 	inc	esi
  2841 00003CB1 46                  <1> 	inc	esi
  2842                              <1> 	;add	si, 2
  2843                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2844                              <1> 			  ; / search table of parent processes 
  2845                              <1> 			  ; / for this process name
  2846 00003CB2 663B86[966C0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2847                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2848                              <1> 			            ; / process number
  2849 00003CB9 7531                <1> 	jne	short syswait_3
  2850                              <1> 		; bne 3f / branch if no match of parent process name
  2851                              <1> 	;inc	cx
  2852 00003CBB FEC1                <1> 	inc	cl
  2853                              <1> 		; inc r3 / yes, a match, r3 indicates number of children
  2854                              <1> 	; 12/02/2022
  2855 00003CBD D1EE                <1> 	shr	esi, 1
  2856                              <1> 	;shr	si, 1
  2857                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2858                              <1> 	; The possible states ('p.stat' values) of a process are:
  2859                              <1> 	;	0 = free or unused
  2860                              <1> 	;	1 = active
  2861                              <1> 	;	2 = waiting for a child process to die
  2862                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2863 00003CBF 80BE[D76C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2864                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2865 00003CC6 7522                <1> 	jne	short syswait_2
  2866                              <1> 		; bne 2f / no, skip it
  2867 00003CC8 88BE[D76C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2868                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2869                              <1> 	; 12/02/2022
  2870 00003CCE D1E6                <1> 	shl	esi, 1
  2871                              <1> 	;shl	si, 1
  2872                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2873 00003CD0 0FB786[766C0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2874 00003CD7 A3[5C6F0000]        <1> 	mov	[u.r0], eax
  2875                              <1> 		; mov p.pid-2(r2),*u.r0 
  2876                              <1> 			      ; / put childs process name in (u.r0)
  2877                              <1> 	;
  2878                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2879                              <1> 	;
  2880                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2881                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2882                              <1> 	; system call loop from the application/program if it calls
  2883                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2884                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2885                              <1> 	;
  2886                              <1> 	; Note: syswait will return with error if there is not a
  2887                              <1> 	;       zombie or running process to wait.	
  2888                              <1> 	;
  2889                              <1> 	;sub	ax, ax
  2890                              <1> 	; 01/02/2022
  2891 00003CDC 29C0                <1> 	sub	eax, eax
  2892 00003CDE 668986[966C0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2893 00003CE5 E913FEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2894                              <1> 	;
  2895                              <1> 	;jmp	sysret
  2896                              <1> 		; br sysret1 / return cause child is dead
  2897                              <1> syswait_2: ; 2:
  2898                              <1> 	; 12/02/2022
  2899 00003CEA D1E6                <1> 	shl	esi, 1
  2900                              <1> 	;shl	si, 1
  2901                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2902                              <1> syswait_3: ; 3:
  2903 00003CEC 6683FE20            <1> 	cmp	si, nproc+nproc
  2904                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2905 00003CF0 72BE                <1> 	jb	short syswait_1
  2906                              <1> 		; blt 1b / no, continue search
  2907                              <1> 	;and	cx, cx
  2908 00003CF2 20C9                <1> 	and	cl, cl
  2909                              <1> 		; tst r3 / one gets here if there are no children 
  2910                              <1> 		       ; / or children that are still active
  2911                              <1> 	; 30/10/2013
  2912 00003CF4 7515                <1> 	jnz	short syswait_4
  2913                              <1> 	;jz	error
  2914                              <1> 		; beq error1 / there are no children, error
  2915 00003CF6 890D[5C6F0000]      <1> 	mov	[u.r0], ecx ; 0
  2916                              <1> 	; 12/02/2022
  2917 00003CFC C705[AB6F0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2917 00003D04 0000                <1>
  2918                              <1> 			; miscellaneous/other errors
  2919 00003D06 E9D0FDFFFF          <1> 	jmp	error
  2920                              <1> syswait_4:
  2921 00003D0B 8A1D[A56F0000]      <1> 	mov	bl, [u.uno]
  2922                              <1> 		; movb u.uno,r1 / there are children so put 
  2923                              <1> 			      ; / parent process number in r1
  2924 00003D11 FE83[D76C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2925                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2926                              <1> 				  ; / other children to die
  2927                              <1> 	; 04/11/2013
  2928 00003D17 E875110000          <1> 	call	swap
  2929                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2930 00003D1C E97BFFFFFF          <1> 	jmp	syswait_0
  2931                              <1> 		; br syswait / wait on next process
  2932                              <1> 
  2933                              <1> sysfork: ; < create a new process >
  2934                              <1> 	; 26/02/2022
  2935                              <1> 	; 25/02/2022
  2936                              <1> 	; 01/02/2022
  2937                              <1> 	; 18/09/2015
  2938                              <1> 	; 04/09/2015
  2939                              <1> 	; 02/09/2015
  2940                              <1> 	; 01/09/2015
  2941                              <1> 	; 28/08/2015
  2942                              <1> 	; 14/05/2015
  2943                              <1> 	; 10/05/2015
  2944                              <1> 	; 09/05/2015
  2945                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2946                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2947                              <1> 	;
  2948                              <1> 	; 'sysfork' creates a new process. This process is referred
  2949                              <1> 	; to as the child process. This new process core image is
  2950                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2951                              <1> 	; distinction is the return location and the fact that (u.r0)
  2952                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2953                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2954                              <1> 	; 'sysfork' works in the following manner: 	
  2955                              <1> 	;    1) The process status table (p.stat) is searched to find
  2956                              <1> 	;	a process number that is unused. If none are found
  2957                              <1> 	;	an error occurs.
  2958                              <1> 	;    2) when one is found, it becomes the child process number
  2959                              <1> 	;	and it's status (p.stat) is set to active.
  2960                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2961                              <1> 	;	character in that tty buffer is cleared.
  2962                              <1> 	;    4) The child process is put on the lowest priority run 
  2963                              <1> 	;	queue via 'putlu'.
  2964                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2965                              <1> 	;	it is a unique number) and is put in the child's unique
  2966                              <1> 	;	identifier; process id (p.pid).
  2967                              <1> 	;    6) The process name of the parent is then obtained and
  2968                              <1> 	;	placed in the unique identifier of the parent process
  2969                              <1> 	;	name is then put in 'u.r0'.	
  2970                              <1> 	;    7) The child process is then written out on disk by
  2971                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2972                              <1> 	;	and the child is born. (The child process is written 
  2973                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2974                              <1> 	;	number.)
  2975                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2976                              <1> 	;    9) The child process name is put in 'u.r0'.
  2977                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2978                              <1> 	;	create the return address for the parent process.
  2979                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2980                              <1> 	;	the parent has opened. For each file the parent has
  2981                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2982                              <1> 	;	to indicate that the child process also has opened
  2983                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2984                              <1> 	;
  2985                              <1> 	; Calling sequence:
  2986                              <1> 	;	from shell ?
  2987                              <1> 	; Arguments:
  2988                              <1> 	;	-
  2989                              <1> 	; Inputs: -
  2990                              <1> 	; Outputs: *u.r0 - child process name
  2991                              <1> 	; ...............................................................
  2992                              <1> 	;	
  2993                              <1> 	; Retro UNIX 8086 v1 modification: 
  2994                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2995                              <1> 	;	= process id of child a parent process returns
  2996                              <1> 	;	= process id of parent when a child process returns
  2997                              <1> 	;
  2998                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  2999                              <1> 	;	in following manner: (with an example: c library, fork)
  3000                              <1> 	;	
  3001                              <1> 	;	1:
  3002                              <1> 	;		sys	fork
  3003                              <1> 	;			br 1f  / child process returns here
  3004                              <1> 	;		bes	2f     / parent process returns here
  3005                              <1> 	;		/ pid of new process in r0
  3006                              <1> 	;		rts	pc
  3007                              <1> 	;	2: / parent process condionally branches here
  3008                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3009                              <1> 	;		rts	pc
  3010                              <1> 	;
  3011                              <1> 	;	1: / child process brances here
  3012                              <1> 	;		clr	r0   / pid = 0 in child process
  3013                              <1> 	;		rts	pc
  3014                              <1> 	;
  3015                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3016                              <1> 	;		// pid = fork();
  3017                              <1> 	;		//
  3018                              <1> 	;		// pid == 0 in child process; 
  3019                              <1> 	;		// pid == -1 means error return
  3020                              <1> 	;		// in child, 
  3021                              <1> 	;		//	parents id is in par_uid if needed
  3022                              <1> 	;		
  3023                              <1> 	;		_fork:
  3024                              <1> 	;			mov	$.fork,eax
  3025                              <1> 	;			int	$0x30
  3026                              <1> 	;			jmp	1f
  3027                              <1> 	;			jnc	2f
  3028                              <1> 	;			jmp	cerror
  3029                              <1> 	;		1:
  3030                              <1> 	;			mov	eax,_par_uid
  3031                              <1> 	;			xor	eax,eax
  3032                              <1> 	;		2:
  3033                              <1> 	;			ret
  3034                              <1> 	;
  3035                              <1> 	;	In Retro UNIX 8086 v1,
  3036                              <1> 	;	'sysfork' returns in following manner:
  3037                              <1> 	;	
  3038                              <1> 	;		mov	ax, sys_fork
  3039                              <1> 	;		mov	bx, offset @f ; routine for child
  3040                              <1> 	;		int	20h
  3041                              <1> 	;		jc	error
  3042                              <1> 	;		
  3043                              <1> 	;	; Routine for parent process here (just after 'jc')
  3044                              <1> 	;		mov	word ptr [pid_of_child], ax
  3045                              <1> 	;		jmp	next_routine_for_parent	
  3046                              <1> 	;
  3047                              <1> 	;	@@: ; routine for child process here				
  3048                              <1> 	;		....	
  3049                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3050                              <1> 	;	       for child process by using BX input.
  3051                              <1> 	;	      (at first, parent process will return then 
  3052                              <1> 	;	      child process will return -after swapped in-
  3053                              <1> 	;	      'syswait' is needed in parent process
  3054                              <1> 	;	      if return from child process will be waited for.)
  3055                              <1> 	;	  				
  3056                              <1> 	
  3057                              <1> ; / create a new process
  3058                              <1> 	; EBX = return address for child process 
  3059                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3060 00003D21 31F6                <1> 	xor 	esi, esi
  3061                              <1> 		; clr r1
  3062                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3063 00003D23 46                  <1> 	inc	esi
  3064                              <1> 		; inc r1
  3065 00003D24 80BE[D76C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3066                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3067 00003D2B 760B                <1> 	jna	short sysfork_2	
  3068                              <1> 		; beq 1f / it's unused so branch
  3069 00003D2D 6683FE10            <1> 	cmp	si, nproc
  3070                              <1> 		; cmp r1,$nproc / all processes checked
  3071 00003D31 72F0                <1> 	jb	short sysfork_1
  3072                              <1> 		; blt 1b / no, branch back
  3073                              <1> 	;
  3074                              <1> 	; Retro UNIX 8086 v1. modification:
  3075                              <1> 	;	Parent process returns from 'sysfork' to address 
  3076                              <1> 	;	which is just after 'sysfork' system call in parent
  3077                              <1> 	;	process. Child process returns to address which is put
  3078                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3079                              <1> 	;
  3080                              <1> 		; add $2,18.(sp) / add 2 to pc when trap occured, points
  3081                              <1> 		               ; / to old process return
  3082                              <1> 		; br error1 / no room for a new process
  3083                              <1> sysfork_err:
  3084 00003D33 E9A3FDFFFF          <1> 	jmp	error
  3085                              <1> sysfork_2: ; 1:
  3086 00003D38 E897F0FFFF          <1> 	call	allocate_page
  3087                              <1> 	;jc	error
  3088                              <1> 	; 01/02/2022
  3089 00003D3D 72F4                <1> 	jc	short sysfork_err
  3090 00003D3F 50                  <1> 	push	eax  ; UPAGE (user structure page) address
  3091                              <1> 	; Retro UNIX 386 v1 modification!
  3092 00003D40 E888F2FFFF          <1> 	call	duplicate_page_dir
  3093                              <1> 		; EAX = New page directory 
  3094 00003D45 7308                <1> 	jnc	short sysfork_3
  3095 00003D47 58                  <1> 	pop	eax  ; UPAGE (user structure page) address
  3096 00003D48 E84FF2FFFF          <1> 	call 	deallocate_page
  3097                              <1> 	;jmp	error
  3098                              <1> 	; 01/02/2022
  3099 00003D4D EBE4                <1> 	jmp	short sysfork_err
  3100                              <1> sysfork_3:
  3101                              <1> 	; Retro UNIX 386 v1 modification !
  3102 00003D4F 56                  <1> 	push	esi
  3103 00003D50 E8B3110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3104                              <1> 		      ; and interrupt return components (for IRET)
  3105 00003D55 8705[AF6F0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3106 00003D5B A3[B36F0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3107 00003D60 5E                  <1> 	pop	esi
  3108 00003D61 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3109                              <1> 		; [u.usp] = esp
  3110 00003D62 89F7                <1> 	mov	edi, esi
  3111                              <1> 	;shl	di, 2
  3112                              <1> 	; 12/02/2022
  3113 00003D64 C1E702              <1> 	shl	edi, 2
  3114 00003D67 8987[E46C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3115 00003D6D A3[A66F0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3116                              <1> 	; 28/08/2015
  3117 00003D72 0FB605[A56F0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3118                              <1> 		; movb u.uno,-(sp) / save parent process number
  3119 00003D79 89C7                <1> 	mov	edi, eax
  3120 00003D7B 50                  <1>         push	eax ; ** 
  3121 00003D7C 8A87[B76C0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3122                              <1> 	; 18/09/2015
  3123 00003D82 8886[B76C0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3124                              <1> 	; 26/02/2022 (p.waitc is not used)
  3125                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3126                              <1> 	; 25/02/2022 (BugFix)
  3127                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3128                              <1> 	;			   ; ah - reset child's wait channel	
  3129 00003D88 89F0                <1> 	mov	eax, esi
  3130 00003D8A A2[A56F0000]        <1> 	mov	[u.uno], al ; child process number
  3131                              <1> 		;movb r1,u.uno / set child process number to r1
  3132 00003D8F FE86[D76C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3133                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3134                              <1> 				  ; / process to active status
  3135                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3136                              <1> 			      ; / control tty buffer in r2
  3137                              <1>                 ; beq 2f / branch, if no such tty assigned
  3138                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3139                              <1> 	; 2:
  3140 00003D95 53                  <1> 	push	ebx  ; * return address for the child process
  3141                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3142                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3143                              <1> 		; mov $runq+4,r2
  3144 00003D96 E8C3110000          <1> 	call	putlu 
  3145                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3146                              <1> 			   ; / run queue
  3147                              <1> 	; 12/02/2022
  3148 00003D9B D1E6                <1> 	shl	esi, 1
  3149                              <1> 	;shl	si, 1
  3150                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3151                              <1> 		       ; / into p.pid table
  3152 00003D9D 66FF05[4A6F0000]    <1> 	inc	word [mpid]
  3153                              <1> 		; inc mpid / increment m.pid; get a new process name
  3154 00003DA4 66A1[4A6F0000]      <1> 	mov	ax, [mpid]
  3155 00003DAA 668986[766C0000]    <1> 	mov	[esi+p.pid-2], ax
  3156                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3157                              <1> 				    ; / in child process' name slot
  3158 00003DB1 5A                  <1> 	pop	edx  ; * return address for the child process
  3159                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3160 00003DB2 5B                  <1>   	pop	ebx  ; **
  3161                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3162                              <1> 		; movb (sp),r2 / put parent process number in r2
  3163                              <1> 	; 01/02/2022
  3164 00003DB3 D0E3                <1> 	shl	bl, 1
  3165                              <1> 	;shl 	bx, 1
  3166                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3167                              <1> 	; ebx <= 32
  3168                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3169 00003DB5 668B83[766C0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3170                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3171                              <1> 				   ; / process
  3172 00003DBC 668986[966C0000]    <1> 	mov	[esi+p.ppid-2], ax
  3173                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3174                              <1> 			  ; / in parent process slot for child
  3175 00003DC3 A3[5C6F0000]        <1> 	mov	[u.r0], eax	
  3176                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3177                              <1> 			     ; / at location where r0 was saved
  3178 00003DC8 8B2D[546F0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3179 00003DCE 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3180                              <1> 			   ; * return address for the child process
  3181                              <1> 		; mov $sysret1,-(sp) /
  3182                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3183                              <1> 			      ; / user is swapped out
  3184                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3185                              <1> 	; 04/09/2015 - 01/09/2015
  3186                              <1> 	; [u.usp] = esp
  3187 00003DD1 68[FB3A0000]        <1> 	push	sysret ; ***
  3188 00003DD6 8925[586F0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3189                              <1> 			     ; (for child process)	
  3190 00003DDC 31C0                <1> 	xor 	eax, eax
  3191 00003DDE 66A3[8C6F0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3192                              <1> 	;
  3193 00003DE4 E81F110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3194                              <1> 		;jsr r0,wswap / put child process out on drum
  3195                              <1> 		;jsr r0,unpack / unpack user stack
  3196                              <1> 		;mov u.usp,sp / restore user stack pointer
  3197                              <1> 		; tst (sp)+ / bump stack pointer
  3198                              <1> 	; Retro UNIX 386 v1 modification !
  3199 00003DE9 58                  <1> 	pop	eax ; ***
  3200                              <1> 	;shl	bx, 1
  3201                              <1> 	; 01/02/2022
  3202 00003DEA D0E3                <1> 	shl	bl, 1 
  3203                              <1> 		; ebx <= 64
  3204 00003DEC 8B83[E46C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3205 00003DF2 E83A110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3206                              <1> 		      ; registers and return address (for IRET)
  3207                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3208 00003DF7 0FB705[4A6F0000]    <1>         movzx   eax, word [mpid]
  3209 00003DFE A3[5C6F0000]        <1> 	mov	[u.r0], eax
  3210                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3211                              <1> 			       ; / where r0 was saved
  3212                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3213                              <1> 			       ; / process return
  3214                              <1> 	;xor	ebx, ebx
  3215 00003E03 31F6                <1> 	xor     esi, esi
  3216                              <1> 		;clr r1
  3217                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3218                              <1> 	      ; / opened by the parent process
  3219                              <1> 	; 01/09/2015
  3220                              <1> 	;xor	bh, bh
  3221                              <1> 	;mov 	bl, [esi+u.fp]
  3222 00003E05 8A86[626F0000]      <1> 	mov 	al, [esi+u.fp]
  3223                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3224                              <1>         ;or	bl, bl
  3225 00003E0B 08C0                <1> 	or	al, al
  3226 00003E0D 740C                <1> 	jz	short sysfork_5	
  3227                              <1> 		; beq 2f / file has not been opened by parent, 
  3228                              <1> 		       ; / so branch
  3229 00003E0F B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3230 00003E11 F6E4                <1> 	mul	ah
  3231                              <1> 	;;movzx	ebx, ax
  3232                              <1> 	;mov	bx, ax
  3233 00003E13 89C3                <1> 	mov	ebx, eax ; 12/02/2022
  3234                              <1> 	;shl	bx, 3
  3235                              <1> 		; asl r2 / multiply by 8
  3236                              <1>        		; asl r2 / to get index into fsp table
  3237                              <1>        		; asl r2
  3238 00003E15 FE83[266D0000]      <1>   	inc     byte [ebx+fsp-2]
  3239                              <1> 		; incb fsp-2(r2) / increment number of processes
  3240                              <1> 			     ; / using file, because child will now be
  3241                              <1> 			     ; / using this file
  3242                              <1> sysfork_5: ; 2:
  3243 00003E1B 46                  <1>         inc     esi
  3244                              <1> 		; inc r1 / get next open file
  3245 00003E1C 6683FE0A            <1>         cmp     si, 10
  3246                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3247                              <1> 			    ; / can be opened
  3248 00003E20 72E3                <1> 	jb	short sysfork_4	
  3249                              <1> 		; blt 1b / check next entry
  3250 00003E22 E9D4FCFFFF          <1> 	jmp	sysret
  3251                              <1> 		; br sysret1
  3252                              <1> 
  3253                              <1> sysread: ; < read from file >
  3254                              <1> 	; 27/02/2022
  3255                              <1> 	; 01/02/2022
  3256                              <1> 	; 13/05/2015
  3257                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3258                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3259                              <1> 	;
  3260                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3261                              <1> 	; characters to be read. If finds the file from the file
  3262                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3263                              <1> 	; is returned from a successful open call (sysopen).
  3264                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3265                              <1> 	; is read into core via 'readi'.
  3266                              <1> 	;
  3267                              <1> 	; Calling sequence:
  3268                              <1> 	;	sysread; buffer; nchars
  3269                              <1> 	; Arguments:
  3270                              <1> 	;	buffer - location of contiguous bytes where 
  3271                              <1> 	;		 input will be placed.
  3272                              <1> 	;	nchars - number of bytes or characters to be read.
  3273                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3274                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3275                              <1> 	; ...............................................................
  3276                              <1> 	;				
  3277                              <1> 	; Retro UNIX 8086 v1 modification: 
  3278                              <1> 	;       'sysread' system call has three arguments; so,
  3279                              <1> 	;	* 1st argument, file descriptor is in BX register
  3280                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3281                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3282                              <1> 	;
  3283                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3284                              <1> 	;	to the user with number of bytes read. 
  3285                              <1> 	;
  3286 00003E27 E840000000          <1> 	call	rw1
  3287                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3288                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3289                              <1>        	; 27/02/2022
  3290 00003E2C 7239                <1> 	jc	short sysread_err
  3291 00003E2E F6C480              <1> 	test	ah, 80h
  3292                              <1> 		; tst r1 / negative i-number?
  3293                              <1> 	;jnz	error
  3294                              <1> 		; ble error1 / yes, error 1 to read
  3295                              <1> 			   ; / it should be positive
  3296                              <1> 	; 01/02/2022
  3297                              <1> 	;jnz	short rw_error
  3298                              <1> 	;27/02/2022
  3299 00003E31 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3300                              <1> 	;
  3301 00003E33 E88D150000          <1> 	call	readi
  3302                              <1> 		; jsr r0,readi / read data into core
  3303 00003E38 EB14                <1> 	jmp	short rw0
  3304                              <1> 		; br 1f
  3305                              <1> 
  3306                              <1> syswrite: ; < write to file >
  3307                              <1> 	; 27/02/2022
  3308                              <1> 	; 01/02/2022
  3309                              <1> 	; 13/05/2015
  3310                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3311                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3312                              <1> 	;
  3313                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3314                              <1> 	; and the number of characters to write. If finds the file
  3315                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3316                              <1> 	; descriptor is returned from a successful open or create call
  3317                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3318                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3319                              <1> 	;
  3320                              <1> 	; Calling sequence:
  3321                              <1> 	;	syswrite; buffer; nchars
  3322                              <1> 	; Arguments:
  3323                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3324                              <1> 	;	nchars - number of characters to be written.
  3325                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3326                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3327                              <1> 	; ...............................................................
  3328                              <1> 	;				
  3329                              <1> 	; Retro UNIX 8086 v1 modification: 
  3330                              <1> 	;       'syswrite' system call has three arguments; so,
  3331                              <1> 	;	* 1st argument, file descriptor is in BX register
  3332                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3333                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3334                              <1> 	;
  3335                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3336                              <1> 	;	to the user with number of bytes written. 
  3337                              <1> 	;
  3338 00003E3A E82D000000          <1> 	call	rw1
  3339                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3340                              <1> 		; jsr r0,rw1 / get i-number in r1 of file to write
  3341                              <1> 	; 01/02/2022
  3342                              <1> 	;jnc	short syswrite_1
  3343                              <1> ;rw_error:
  3344                              <1> 	;jmp	error
  3345                              <1> 	; 27/02/2022
  3346 00003E3F 7226                <1> 	jc	short short syswrite_err
  3347                              <1> syswrite_1:
  3348 00003E41 F6C480              <1>         test	ah, 80h
  3349                              <1> 		; tst r1 / positive i-number ?
  3350 00003E44 7417                <1>         jz	short rw3 ; 13/05/2015
  3351                              <1> 	;jz	error
  3352                              <1> 		; bge error1 / yes, error 1 
  3353                              <1> 			   ; / negative i-number means write
  3354 00003E46 66F7D8              <1> 	neg	ax
  3355                              <1> 		; neg r1 / make it positive
  3356 00003E49 E865170000          <1> 	call	writei
  3357                              <1>         	; jsr r0,writei / write data
  3358                              <1> rw0: ; 1:
  3359 00003E4E A1[846F0000]        <1>         mov	eax, [u.nread]
  3360 00003E53 A3[5C6F0000]        <1> 	mov	[u.r0], eax
  3361                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3362                              <1> 				  ; / into (u.r0)
  3363 00003E58 E99EFCFFFF          <1> 	jmp	sysret
  3364                              <1>         	; br sysret1
  3365                              <1> rw3: 
  3366                              <1> 	; 13/05/2015
  3367 00003E5D C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3367 00003E65 0000                <1>
  3368                              <1> 	;stc
  3369                              <1> 	;retn
  3370                              <1> 	; 27/02/2022 (BugFix)
  3371                              <1> sysread_err:
  3372                              <1> syswrite_err:
  3373 00003E67 E96FFCFFFF          <1> 	jmp	error
  3374                              <1> 
  3375                              <1> rw1:	
  3376                              <1> 	; 14/05/2015
  3377                              <1> 	; 13/05/2015
  3378                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3379                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3380                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3381                              <1> 	;
  3382                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3383                              <1> 				;(in the user's virtual memory space)
  3384                              <1> 	;mov	[u.count], edx 
  3385                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3386                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3387                              <1> 	;;mov	eax, ebx ; file descriptor
  3388                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3389                              <1> 		             ; / (index to u.fp table) in r1
  3390                              <1> 	; 13/05/2015
  3391 00003E6C C705[5C6F0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3391 00003E74 0000                <1>
  3392                              <1> 	;
  3393                              <1> 	;; call	getf
  3394                              <1>         ; eBX = File descriptor
  3395 00003E76 E82E0B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3396                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3397                              <1> 	; AX = I-number of the file ; negative i-number means write
  3398                              <1> 	; 13/05/2015
  3399 00003E7B 6683F801            <1> 	cmp 	ax, 1
  3400 00003E7F 7217                <1> 	jb	short rw2
  3401                              <1> 	;
  3402 00003E81 890D[7C6F0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3403                              <1> 				;(in the user's virtual memory space)
  3404 00003E87 8915[806F0000]      <1> 	mov	[u.count], edx 
  3405                              <1> 	; 14/05/2015
  3406 00003E8D C705[AB6F0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3406 00003E95 0000                <1>
  3407 00003E97 C3                  <1> 	retn
  3408                              <1>         	; rts r0
  3409                              <1> rw2:
  3410                              <1> 	; 13/05/2015
  3411 00003E98 C705[AB6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3411 00003EA0 0000                <1>
  3412 00003EA2 C3                  <1> 	retn
  3413                              <1> 
  3414                              <1> sysopen: ;<open file>
  3415                              <1> 	; 12/02/2022
  3416                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3417                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3418                              <1> 	;
  3419                              <1> 	; 'sysopen' opens a file in following manner:
  3420                              <1> 	;    1) The second argument in a sysopen says whether to
  3421                              <1> 	;	open the file ro read (0) or write (>0).
  3422                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3423                              <1> 	;    3) The file is opened by 'iopen'.
  3424                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3425                              <1> 	;	and the user's open file list - u.fp.
  3426                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3427                              <1> 	;	b) An entry for the file is created in the fsp table.
  3428                              <1> 	;	c) The number of this entry is put on u.fp list.
  3429                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3430                              <1> 	;	   to by u.r0.
  3431                              <1> 	;
  3432                              <1> 	; Calling sequence:
  3433                              <1> 	;	sysopen; name; mode
  3434                              <1> 	; Arguments:
  3435                              <1> 	;	name - file name or path name
  3436                              <1> 	;	mode - 0 to open for reading
  3437                              <1> 	;	       1 to open for writing
  3438                              <1> 	; Inputs: (arguments)
  3439                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3440                              <1> 	;		  is put into r0's location on the stack.	
  3441                              <1> 	; ...............................................................
  3442                              <1> 	;				
  3443                              <1> 	; Retro UNIX 8086 v1 modification: 
  3444                              <1> 	;       'sysopen' system call has two arguments; so,
  3445                              <1> 	;	* 1st argument, name is pointed to by BX register
  3446                              <1> 	;	* 2nd argument, mode is in CX register
  3447                              <1> 	;
  3448                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3449                              <1> 	;	to the user with the file descriptor/number 
  3450                              <1> 	;	(index to u.fp list).
  3451                              <1> 	;
  3452                              <1> 	;call	arg2
  3453                              <1> 	; * name - 'u.namep' points to address of file/path name
  3454                              <1> 	;          in the user's program segment ('u.segmnt')
  3455                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3456                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3457                              <1> 	;          which is on top of stack.
  3458                              <1> 	;
  3459                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3460                              <1> 	;
  3461                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3462                              <1> 
  3463 00003EA3 891D[746F0000]      <1> 	mov	[u.namep], ebx
  3464                              <1> 	;push	cx
  3465 00003EA9 51                  <1> 	push	ecx ; 12/02/2022
  3466 00003EAA E82D0B0000          <1> 	call	namei
  3467                              <1> 		; jsr r0,namei / i-number of file in r1
  3468                              <1>      	;and	ax, ax
  3469                              <1> 	;jz	error ; File not found
  3470 00003EAF 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3471                              <1> 	;jc	error ; 27/05/2013
  3472                              <1> 		; br  error2 / file not found
  3473                              <1>    	;pop	dx ; mode
  3474                              <1> 	;push	dx
  3475                              <1> 	; 12/02/2022
  3476                              <1> 	;pop	edx ; * ; mode
  3477                              <1> 	;push	edx ; *
  3478 00003EB1 8B1424              <1> 	mov	edx, [esp] ; *
  3479                              <1> 	; edx = open mode (0 or 1)
  3480                              <1> 	;or	dx, dx
  3481 00003EB4 08D2                <1> 	or	dl, dl
  3482                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3483                              <1> 		         ; / 0 means, open for read)
  3484 00003EB6 7403                <1> 	jz	short sysopen_0
  3485                              <1> 		; beq 1f / yes, leave i-number positive
  3486                              <1> syscreat_0: 
  3487                              <1> 	; 12/02/2022 (v1.0, 2022) ; 27/12/2015 (v1.1)
  3488 00003EB8 66F7D8              <1> 	neg	ax
  3489                              <1>         	; neg r1 / open for writing so make i-number negative
  3490                              <1> sysopen_0: ;1:
  3491 00003EBB E8161B0000          <1> 	call	iopen
  3492                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3493 00003EC0 5A                  <1> 	pop	edx ; * ; mode ; 12/02/2022
  3494                              <1> 	;and	dx, dx
  3495 00003EC1 20D2                <1> 	and	dl, dl
  3496                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3497 00003EC3 7403                <1> 	jz	short sysopen_2
  3498                              <1>         	; beq op1 / is open for read op1
  3499                              <1> sysopen_1: ;op0:
  3500 00003EC5 66F7D8              <1> 	neg	ax
  3501                              <1>         	; neg r1 
  3502                              <1> 		     ;/ make i-number positive if open for writing [???]
  3503                              <1> 	;; NOTE: iopen always make i-number positive.
  3504                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3505                              <1> sysopen_2: ;op1:
  3506 00003EC8 31F6                <1>         xor     esi, esi
  3507                              <1>         	; clr r2 / clear registers
  3508 00003ECA 31DB                <1>         xor     ebx, ebx
  3509                              <1> 		; clr r3
  3510                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3511 00003ECC 389E[626F0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3512                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3513 00003ED2 7625                <1>         jna	short sysopen_4
  3514                              <1> 		; beq 1f / if byte in list is 0 branch
  3515 00003ED4 46                  <1>         inc     esi
  3516                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3517 00003ED5 6683FE0A            <1>         cmp     si, 10
  3518                              <1> 		; cmp r2,$10. / reached end of list?
  3519 00003ED9 72F1                <1> 	jb	short sysopen_3
  3520                              <1> 		; blt 1b / no, go back
  3521                              <1> toomanyf:
  3522                              <1> 	; 14/05/2015
  3523 00003EDB C705[AB6F0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3523 00003EE3 0000                <1>
  3524 00003EE5 E9F1FBFFFF          <1> 	jmp	error
  3525                              <1>         	; br error2 / yes, error (no files open)
  3526                              <1> fnotfound: 
  3527                              <1> 	; 14/05/2015
  3528 00003EEA C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3528 00003EF2 0000                <1>
  3529 00003EF4 E9E2FBFFFF          <1> 	jmp	error
  3530                              <1> 
  3531                              <1> sysopen_4: ; 1:
  3532 00003EF9 6683BB[286D0000]00  <1>         cmp     word [ebx+fsp], 0
  3533                              <1> 		; tst fsp(r3) / scan fsp entries
  3534 00003F01 7610                <1>         jna     short sysopen_5
  3535                              <1> 		; beq 1f / if 0 branch
  3536                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3537 00003F03 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3538                              <1> 		; add $8.,r3 / add 8 to r3 
  3539                              <1> 			; / to bump it to next entry mfsp table
  3540 00003F07 6681FBF401          <1>         cmp     bx, nfiles*10
  3541                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3542 00003F0C 72EB                <1> 	jb	short sysopen_4
  3543                              <1>        		; blt 1b / no, back
  3544 00003F0E E9C8FBFFFF          <1> 	jmp	error
  3545                              <1>         	; br error2 / yes, error
  3546                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3547 00003F13 668983[286D0000]    <1>         mov     [ebx+fsp], ax
  3548                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3549                              <1> 			; / into next available entry in fsp table,
  3550                              <1> 	; 12/02/2022
  3551                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3552                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3553                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3554                              <1> 	;xor	edi, edi
  3555                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3556                              <1> 	;	; clr fsp+4(r3)
  3557                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3558                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3559 00003F1A 31C0                <1> 	xor	eax, eax
  3560 00003F1C 8983[2C6D0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3561 00003F22 668983[306D0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3562                              <1> 
  3563 00003F29 66A1[406F0000]      <1> 	mov	ax, [cdev]
  3564 00003F2F 668983[2A6D0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3565                              <1> 
  3566 00003F36 89D8                <1>   	mov	eax, ebx
  3567 00003F38 B30A                <1> 	mov	bl, 10
  3568 00003F3A F6F3                <1> 	div	bl 
  3569                              <1> 		; asr r3
  3570                              <1> 		; asr r3 / divide by 8 
  3571                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3572 00003F3C FEC0                <1> 	inc	al
  3573                              <1>         	; inc r3 / add 1 to get fsp entry number
  3574 00003F3E 8886[626F0000]      <1>         mov     [esi+u.fp], al
  3575                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3576                              <1> 			; / next available slot in u.fp list
  3577 00003F44 8935[5C6F0000]      <1>         mov     [u.r0], esi
  3578                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3579                              <1> 			     ; / into r0 loc on stack
  3580 00003F4A E9ACFBFFFF          <1>         jmp	sysret
  3581                              <1> 		; br sysret2
  3582                              <1> 
  3583                              <1> 	;
  3584                              <1> 	; 'fsp' table (10 bytes/entry)
  3585                              <1> 	; bit 15				   bit 0
  3586                              <1> 	; ---|-------------------------------------------
  3587                              <1> 	; r/w|		i-number of open file
  3588                              <1> 	; ---|-------------------------------------------
  3589                              <1> 	;		   device number
  3590                              <1> 	; -----------------------------------------------
  3591                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3592                              <1> 	; -----------------------------------------------
  3593                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3594                              <1> 	; ----------------------|------------------------
  3595                              <1> 	;  flag that says file 	| number of processes
  3596                              <1> 	;   has been deleted	| that have file open 
  3597                              <1> 	; ----------------------|------------------------
  3598                              <1> 	;
  3599                              <1> 
  3600                              <1> syscreat: ; < create file >
  3601                              <1> 	; 12/02/2022
  3602                              <1> 	; 01/02/2022
  3603                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3604                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3605                              <1> 	;
  3606                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3607                              <1> 	; u.namep points to name of the file and mode is put
  3608                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3609                              <1> 	; If the file aready exists, it's mode and owner remain 
  3610                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3611                              <1> 	; did not exist, an i-node is created with the new mode via
  3612                              <1> 	; 'maknod' whether or not the file already existed, it is
  3613                              <1> 	; open for writing. The fsp table is then searched for a free
  3614                              <1> 	; entry. When a free entry is found, proper data is placed
  3615                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3616                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3617                              <1> 	; is put in the user's r0. 			
  3618                              <1> 	;
  3619                              <1> 	; Calling sequence:
  3620                              <1> 	;	syscreate; name; mode
  3621                              <1> 	; Arguments:
  3622                              <1> 	;	name - name of the file to be created
  3623                              <1> 	;	mode - mode of the file to be created
  3624                              <1> 	; Inputs: (arguments)
  3625                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3626                              <1> 	;		   (the file descriptor of new file)
  3627                              <1> 	; ...............................................................
  3628                              <1> 	;				
  3629                              <1> 	; Retro UNIX 8086 v1 modification: 
  3630                              <1> 	;       'syscreate' system call has two arguments; so,
  3631                              <1> 	;	* 1st argument, name is pointed to by BX register
  3632                              <1> 	;	* 2nd argument, mode is in CX register
  3633                              <1> 	;
  3634                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3635                              <1> 	;	to the user with the file descriptor/number 
  3636                              <1> 	;	(index to u.fp list).
  3637                              <1> 	;
  3638                              <1> 	;call	arg2
  3639                              <1> 	; * name - 'u.namep' points to address of file/path name
  3640                              <1> 	;          in the user's program segment ('u.segmnt')
  3641                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3642                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3643                              <1> 	;          which is on top of stack.
  3644                              <1> 	;
  3645                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3646                              <1> 			    ; / on stack
  3647 00003F4F 891D[746F0000]      <1> 	mov	[u.namep], ebx ; file name address
  3648                              <1> 	;push	cx ; mode
  3649                              <1> 	; 01/02/2022
  3650 00003F55 51                  <1> 	push	ecx ; mode
  3651 00003F56 E8810A0000          <1> 	call 	namei        	
  3652                              <1> 		; jsr r0,namei / get the i-number
  3653                              <1>         ;and	ax, ax
  3654                              <1> 	;jz	short syscreat_2	       	
  3655 00003F5B 721B                <1> 	jc	short syscreat_2
  3656                              <1> 		; br  2f / if file doesn't exist 2f
  3657                              <1> 	; 12/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18, 2022)
  3658                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3659 00003F5D 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3660                              <1>         ;jb	syscreat_0 ; yes
  3661                              <1> 	; 02/02/2022
  3662 00003F61 7305                <1> 	jnb	short syscreat_1
  3663 00003F63 E950FFFFFF          <1> 	jmp	syscreat_0
  3664                              <1> syscreat_1:
  3665 00003F68 66F7D8              <1> 	neg 	ax
  3666                              <1>         	; neg r1 / if file already exists make i-number 
  3667                              <1> 		       ; / negative (open for writing)
  3668 00003F6B E8661A0000          <1> 	call	iopen
  3669                              <1>         	; jsr r0,iopen /
  3670 00003F70 E8A8130000          <1> 	call	itrunc
  3671                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3672                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3673                              <1> 	; 01/02/2022
  3674 00003F75 59                  <1> 	pop	ecx ; mode
  3675                              <1> 	; 12/02/2022
  3676 00003F76 EB0E                <1> 	jmp	short syscreat_3
  3677                              <1>         ;jmp	sysopen_1
  3678                              <1>         	; br op0
  3679                              <1> syscreat_2: ; 2: / file doesn't exist
  3680                              <1> 	; 01/02/2022
  3681 00003F78 58                  <1> 	pop	eax ; mode
  3682                              <1> 	;pop	ax
  3683                              <1>         	; mov (sp)+,r1 / put the mode in r1
  3684 00003F79 30E4                <1> 	xor	ah, ah	
  3685                              <1>         	; bic $!377,r1 / clear upper byte
  3686 00003F7B E86D0D0000          <1> 	call 	maknod
  3687                              <1>         	; jsr r0,maknod / make an i-node for this file
  3688 00003F80 66A1[8E6F0000]      <1> 	mov	ax, [u.dirbuf]
  3689                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3690                              <1> 			        ; / for this new file in r1
  3691                              <1> syscreat_3:
  3692 00003F86 E93AFFFFFF          <1>         jmp     sysopen_1
  3693                              <1>         	; br op0 / open the file
  3694                              <1> 
  3695                              <1> sysmkdir: ; < make directory >
  3696                              <1> 	; 01/02/2022
  3697                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3698                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3699                              <1> 	;
  3700                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3701                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3702                              <1> 	; The special entries '.' and '..' are not present.
  3703                              <1> 	; Errors are indicated if the directory already exists or		
  3704                              <1> 	; user is not the super user. 
  3705                              <1> 	;
  3706                              <1> 	; Calling sequence:
  3707                              <1> 	;	sysmkdir; name; mode
  3708                              <1> 	; Arguments:
  3709                              <1> 	;	name - points to the name of the directory
  3710                              <1> 	;	mode - mode of the directory
  3711                              <1> 	; Inputs: (arguments)
  3712                              <1> 	; Outputs: -
  3713                              <1> 	;    (sets 'directory' flag to 1; 
  3714                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3715                              <1> 	; ...............................................................
  3716                              <1> 	;				
  3717                              <1> 	; Retro UNIX 8086 v1 modification: 
  3718                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3719                              <1> 	;	* 1st argument, name is pointed to by BX register
  3720                              <1> 	;	* 2nd argument, mode is in CX register
  3721                              <1> 		
  3722                              <1> ; / make a directory
  3723                              <1> 	
  3724                              <1> 	;call	arg2
  3725                              <1> 	; * name - 'u.namep' points to address of file/path name
  3726                              <1> 	;          in the user's program segment ('u.segmnt')
  3727                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3728                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3729                              <1> 	;          which is on top of stack.
  3730                              <1> 
  3731                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3732                              <1> 			    ; / on stack
  3733 00003F8B 891D[746F0000]      <1> 	mov	[u.namep], ebx
  3734                              <1> 	;push	cx ; mode
  3735                              <1> 	; 01/02/2022
  3736 00003F91 51                  <1> 	push	ecx ; mode
  3737 00003F92 E8450A0000          <1> 	call	namei
  3738                              <1>         	; jsr r0,namei / get the i-number
  3739                              <1>         	;     br .+4 / if file not found branch around error
  3740                              <1>         ;xor 	ax, ax
  3741                              <1> 	;jnz	error
  3742 00003F97 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3743                              <1> 	;jnc	error	
  3744                              <1> 		; br  error2 / directory already exists (error)
  3745 00003F99 803D[A26F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3746                              <1>         	;tstb u.uid / is user the super user
  3747                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3748                              <1> 	;;jna	error
  3749                              <1> 	; 01/02/2022 (BugFix)
  3750 00003FA0 7721                <1> 	ja	short dir_access_err
  3751                              <1>         	;bne error2 / no, not allowed
  3752                              <1> 	;pop	ax
  3753                              <1> 	; 01/02/2022
  3754 00003FA2 58                  <1> 	pop	eax ; mode
  3755                              <1>         	;mov (sp)+,r1 / put the mode in r1
  3756 00003FA3 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3757                              <1>         	;bic $!317,r1 / all but su and ex
  3758                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3759 00003FA7 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3760                              <1>         	;bis $40000,r1 / directory flag
  3761 00003FAA E83E0D0000          <1> 	call	maknod
  3762                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3763                              <1> sysclose_sysret: ; 01/02/2022
  3764 00003FAF E947FBFFFF          <1> 	jmp	sysret
  3765                              <1>         	;br sysret2 /
  3766                              <1> dir_exists:
  3767                              <1> 	; 14/05/2015
  3768 00003FB4 C705[AB6F0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3768 00003FBC 0000                <1>
  3769 00003FBE E918FBFFFF          <1> 	jmp	error
  3770                              <1> dir_access_err:
  3771                              <1> 	; 14/05/2015
  3772 00003FC3 C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3772 00003FCB 0000                <1>
  3773 00003FCD E909FBFFFF          <1> 	jmp	error
  3774                              <1> 
  3775                              <1> sysclose: ;<close file>
  3776                              <1> 	; 01/02/2022
  3777                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3778                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3779                              <1> 	;
  3780                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3781                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3782                              <1> 	; is put in r1 and 'fclose' is called.
  3783                              <1> 	;
  3784                              <1> 	; Calling sequence:
  3785                              <1> 	;	sysclose
  3786                              <1> 	; Arguments:
  3787                              <1> 	;	-  
  3788                              <1> 	; Inputs: *u.r0 - file descriptor
  3789                              <1> 	; Outputs: -
  3790                              <1> 	; ...............................................................
  3791                              <1> 	;				
  3792                              <1> 	; Retro UNIX 8086 v1 modification:
  3793                              <1> 	;	 The user/application program puts file descriptor
  3794                              <1> 	;        in BX register as 'sysclose' system call argument.
  3795                              <1> 	; 	 (argument transfer method 1)
  3796                              <1> 
  3797                              <1> 	; / close the file
  3798                              <1> 	
  3799 00003FD2 89D8                <1> 	mov 	eax, ebx
  3800 00003FD4 E88D090000          <1> 	call 	fclose
  3801                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3802                              <1> 		; jsr r0,fclose / close the file
  3803                              <1>                	; br error2 / unknown file descriptor
  3804                              <1> 		; br sysret2
  3805                              <1> 	; 14/05/2015
  3806                              <1> 	;jnc	sysret
  3807                              <1> 	; 01/02/2022
  3808 00003FD9 73D4                <1> 	jnc	short sysclose_sysret
  3809 00003FDB C705[AB6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3809 00003FE3 0000                <1>
  3810 00003FE5 E9F1FAFFFF          <1> 	jmp	error
  3811                              <1> 
  3812                              <1> sysemt:
  3813                              <1> 	; 23/02/2022
  3814                              <1> 	; 01/02/2022
  3815                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3816                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3817                              <1> 	;
  3818                              <1> 	; Retro UNIX 8086 v1 modification: 
  3819                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3820                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3821                              <1> 	;
  3822                              <1> 	; Retro UNIX 8086 v1 feature only!
  3823                              <1> 	;	Using purpose: Kernel will start without time-out
  3824                              <1> 	;	(internal clock/timer) functionality.
  3825                              <1> 	;	Then etc/init will enable clock/timer for
  3826                              <1> 	;	multi tasking. (Then it will not be disabled again
  3827                              <1> 	;	except hardware reset/restart.)
  3828                              <1> 
  3829 00003FEA 803D[A26F0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3830                              <1> 	;;ja	error
  3831                              <1> 	;ja	badsys ; 14/05/2015
  3832                              <1> 	; 01/02/2022
  3833                              <1> 	;jna	short emt_0
  3834                              <1> 	;jmp	badsys
  3835 00003FF1 773A                <1> 	ja	short sysilgins ; jmp badsys
  3836                              <1> emt_0:
  3837 00003FF3 FA                  <1> 	cli
  3838 00003FF4 21DB                <1> 	and	ebx, ebx
  3839 00003FF6 7429                <1> 	jz	short emt_2
  3840                              <1> 	; Enable multi tasking -time sharing-
  3841 00003FF8 B8[A64F0000]        <1> 	mov	eax, clock ; enable multi tasking clock/timer
  3842                              <1> 	; 23/02/2022
  3843 00003FFD BA[620A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3844                              <1> emt_1:
  3845 00004002 A3[28070000]        <1> 	mov	[x_timer], eax
  3846                              <1> 	; 23/02/2022 (Temporary)
  3847 00004007 8915[2C070000]      <1> 	mov	[x_rtci], edx
  3848 0000400D B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3849 0000400F E853020000          <1> 	call	wttyc  ; clear video page
  3850 00004014 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3851 00004016 E84C020000          <1> 	call	wttyc  ; clear video page
  3852                              <1> 	;
  3853 0000401B FB                  <1> 	sti
  3854 0000401C E9DAFAFFFF          <1> 	jmp	sysret
  3855                              <1> emt_2:
  3856                              <1> 	; Disable multi tasking -time sharing-
  3857 00004021 B8[34070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3858                              <1> 	; 23/02/2022
  3859 00004026 BA[690A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3860                              <1> 	;
  3861 0000402B EBD5                <1> 	jmp	short emt_1
  3862                              <1> 
  3863                              <1> 	; Original UNIX v1 'sysemt' routine
  3864                              <1> ;sysemt:
  3865                              <1>         ;
  3866                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3867                              <1> 			 ; / in loc 30
  3868                              <1>         ;cmp    30,$core / was the argument a lower address 
  3869                              <1> 			; / than core
  3870                              <1>         ;blo    1f / yes, rtssym
  3871                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3872                              <1> 			; / and less than "ecore"
  3873                              <1>         ;blo    2f / yes, sysret2
  3874                              <1> ;1:
  3875                              <1>         ;mov    $rtssym,30
  3876                              <1> ;2:
  3877                              <1>         ;br     sysret2
  3878                              <1> 
  3879                              <1> 	; 01/02/2022
  3880                              <1> sysilgins:
  3881                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3882                              <1> 	; 03/06/2013
  3883                              <1> 	; Retro UNIX 8086 v1 modification: 
  3884                              <1> 	;	not a valid system call ! (not in use)
  3885                              <1> 	;
  3886 0000402D E952FBFFFF          <1> 	jmp	badsys
  3887                              <1> 	;jmp	error
  3888                              <1> 	;;jmp 	sysret
  3889                              <1> 
  3890                              <1> 	; Original UNIX v1 'sysemt' routine
  3891                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3892                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3893                              <1> 			  ;/ put it in loc 8.,
  3894                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3895                              <1> 		       ; / trap address
  3896                              <1>         ;blo    1f / is the address a user core address?  
  3897                              <1> 		; / yes, go to 2f
  3898                              <1>         ;cmp    10,$ecore
  3899                              <1>         ;blo    2f
  3900                              <1> ;1:
  3901                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3902                              <1> 		    ; / instruction trap address for the system
  3903                              <1> ;2:
  3904                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3905                              <1> 
  3906                              <1> sysmdate: ; < change the modification time of a file >
  3907                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3908                              <1> 	;	(ECX input)
  3909                              <1> 	; 01/02/2022
  3910                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3911                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3912                              <1> 	;
  3913                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3914                              <1> 	; file into core. The user is checked if he is the owner 
  3915                              <1> 	; or super user. If he is neither an error occurs.
  3916                              <1> 	; 'setimod' is then called to set the i-node modification
  3917                              <1> 	; byte and the modification time, but the modification time
  3918                              <1> 	; is overwritten by whatever get put on the stack during
  3919                              <1> 	; a 'systime' system call. This calls are restricted to
  3920                              <1> 	; the super user.		
  3921                              <1> 	;
  3922                              <1> 	; Calling sequence:
  3923                              <1> 	;	sysmdate; name
  3924                              <1> 	; Arguments:
  3925                              <1> 	;	name - points to the name of file
  3926                              <1> 	; Inputs: (arguments)
  3927                              <1> 	; Outputs: -
  3928                              <1> 	; ...............................................................
  3929                              <1> 	;				
  3930                              <1> 	; Retro UNIX 8086 v1 modification: 
  3931                              <1> 	;	 The user/application program puts address 
  3932                              <1> 	;	 of the file name in BX register 
  3933                              <1> 	;	 as 'sysmdate' system call argument.
  3934                              <1> 	;
  3935                              <1> ; / change the modification time of a file
  3936                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3937 00004032 891D[746F0000]      <1>         mov	[u.namep], ebx
  3938                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3939 00004038 890D[E06B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3940 0000403E E899090000          <1> 	call	namei
  3941                              <1> 		; jsr r0,namei / get its i-number
  3942                              <1> 	;;jc	error       
  3943                              <1> 		; br error2 / no, such file
  3944                              <1> 	;jc	fnotfound ; file not found !
  3945                              <1> 	; 01/02/2022
  3946 00004043 7305                <1> 	jnc	short mdate_0
  3947 00004045 E9A0FEFFFF          <1> 	jmp	fnotfound
  3948                              <1> mdate_0:
  3949 0000404A E8A2110000          <1> 	call	iget
  3950                              <1> 		; jsr r0,iget / get i-node into core
  3951 0000404F A0[A26F0000]        <1> 	mov	al, [u.uid]
  3952 00004054 3A05[5B6C0000]      <1> 	cmp	al, [i.uid]
  3953                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  3954 0000405A 7413                <1> 	je	short mdate_1
  3955                              <1>         	; beq 1f / yes
  3956 0000405C 20C0                <1> 	and	al, al
  3957                              <1> 		; tstb u.uid / no, is user the super user
  3958                              <1> 	;jnz	error
  3959                              <1> 		; bne error2 / no, error
  3960 0000405E 740F                <1> 	jz	short mdate_1
  3961 00004060 C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3961 00004068 0000                <1>
  3962                              <1> sysstty_err:	; 01/02/2022
  3963 0000406A E96CFAFFFF          <1> 	jmp	error
  3964                              <1> mdate_1: ;1:
  3965 0000406F E887120000          <1> 	call	setimod
  3966                              <1>         	; jsr r0,setimod / fill in modification data,
  3967                              <1> 		               ; / time etc.
  3968 00004074 BE[E06B0000]        <1> 	mov	esi, p_time
  3969 00004079 BF[726C0000]        <1> 	mov	edi, i.mtim
  3970 0000407E A5                  <1> 	movsd
  3971                              <1> 		; mov 4(sp),i.mtim / move present time to
  3972                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  3973 0000407F E977FAFFFF          <1>         jmp	sysret
  3974                              <1> 		; br sysret2
  3975                              <1> 
  3976                              <1> 	; 01/02/2022
  3977                              <1> sysstty_err_s:
  3978 00004084 880D[5C6F0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  3979 0000408A EBDE                <1> 	jmp	short sysstty_err
  3980                              <1> 
  3981                              <1> sysstty: ; < set tty status and mode >
  3982                              <1> 	; 23/02/2022
  3983                              <1> 	; 22/02/2022
  3984                              <1> 	; 02/02/2022
  3985                              <1> 	; 01/02/2022 (clear screen)
  3986                              <1> 	; 17/11/2015
  3987                              <1> 	; 12/11/2015
  3988                              <1> 	; 29/10/2015
  3989                              <1> 	; 17/10/2015
  3990                              <1> 	; 13/10/2015
  3991                              <1> 	; 29/06/2015
  3992                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  3993                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  3994                              <1> 	;
  3995                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  3996                              <1> 	; whose file descriptor is in (u.r0).
  3997                              <1> 	;
  3998                              <1> 	; Calling sequence:
  3999                              <1> 	;	sysstty; arg
  4000                              <1> 	; Arguments:
  4001                              <1> 	;	arg - address of 3 consequitive words that contain
  4002                              <1> 	;	      the source of status data	
  4003                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4004                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4005                              <1> 	; ...............................................................
  4006                              <1> 	;	
  4007                              <1> 	; Retro UNIX 8086 v1 modification: 
  4008                              <1> 	;	'sysstty' system call will set the tty
  4009                              <1> 	;	(clear keyboard buffer and set cursor position)
  4010                              <1> 	;	 in following manner:
  4011                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4012                              <1> 	;
  4013                              <1> 	; Inputs:
  4014                              <1> 	;	BX = 0 --> means
  4015                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4016                              <1> 	;	      set cursor position for console tty, only 
  4017                              <1> 	;	      CH will be ignored (char. will not be written)	
  4018                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4019                              <1> 	;	      set console tty for (current) process
  4020                              <1> 	;	      CL = tty number (0 to 9)
  4021                              <1> 	;	      (If CH = 0, character will not be written)
  4022                              <1> 	;          If CH > 0 (CL < FFh)	
  4023                              <1> 	;             CL = tty number (0 to 9)
  4024                              <1> 	;	      CH = character will be written
  4025                              <1> 	;	        at requested cursor position (in DX)	
  4026                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4027                              <1>   	;		(only tty number 0 to 7) 
  4028                              <1> 	;          DL = communication parameters (for serial ports) 
  4029                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4030                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4031                              <1> 	;			or set cursor position	
  4032                              <1> 	;	   DH = 0FFh -> DL is not valid
  4033                              <1> 	;		do not set serial port parameters 
  4034                              <1> 	;		or do not set cursor position
  4035                              <1> 	;
  4036                              <1> 	;	BX > 0 --> points to name of tty
  4037                              <1> 	;    	   CH > 0 -->
  4038                              <1> 	;		CH = character will be written in current 
  4039                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4040                              <1> 	;	     	or character will be sent to serial port
  4041                              <1> 	;	     	(for tty number 8 or 9)
  4042                              <1> 	;		CL = color of the character if tty number < 8.
  4043                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4044                              <1> 	;		set mode (tty 8 to 9) or 
  4045                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4046                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4047                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4048                              <1> 	;		(DL is not valid)
  4049                              <1> 	;	   DL = communication parameters 
  4050                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4051                              <1> 	;
  4052                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4053                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4054                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4055                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4056                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4057                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4058                              <1> 	;
  4059                              <1> 	; Outputs:
  4060                              <1> 	;	cf = 0 -> OK
  4061                              <1> 	;	     AL = tty number (0 to 9)
  4062                              <1> 	;	     AH = line status if tty number is 8 or 9
  4063                              <1> 	;	     AH = process number (of the caller) 	
  4064                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4065                              <1> 	;	     AH = FFh if the tty is locked 
  4066                              <1> 	;		  (owned by another process)
  4067                              <1> 	;	        = process number (of the caller) 
  4068                              <1> 	;		  (if < FFh and tty number < 8)
  4069                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4070                              <1> 	;	     AH = line status if tty number is 8 or 9
  4071                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4072                              <1> 	;	
  4073                              <1> 
  4074                              <1> 	; 27/06/2015 (32 bit modifications)
  4075                              <1> 	; 14/01/2014
  4076 0000408C 31C0                <1> 	xor 	eax, eax
  4077 0000408E 6648                <1> 	dec	ax ; 17/10/2015
  4078 00004090 A3[5C6F0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4079                              <1> 	;;;
  4080                              <1> 	; 01/02/2022
  4081 00004095 FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4082 00004097 39C2                <1> 	cmp	edx, eax
  4083                              <1> 	;cmp	dx, ax ; 0FFFFh
  4084 00004099 7521                <1> 	jne	short sysstty_18
  4085                              <1> 	; clear video page
  4086                              <1> 	; (CH must be 0)
  4087 0000409B 08ED                <1> 	or	ch, ch
  4088 0000409D 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4089 0000409F 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4090 000040A2 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4091 000040A4 20C9                <1> 	and	cl, cl
  4092 000040A6 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4093 000040A8 0FB635[A56F0000]    <1> 	movzx	esi, byte [u.uno]
  4094 000040AF 8A8E[B76C0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4095 000040B5 80F907              <1> 	cmp	cl, 7
  4096 000040B8 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4097                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4098 000040BA FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4099                              <1> sysstty_18:
  4100 000040BC FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4101                              <1> 	; cl = video page (tty) number		
  4102                              <1> 	;;;
  4103 000040BE 21DB                <1> 	and	ebx, ebx
  4104                              <1> 	;jnz	sysstty_6
  4105                              <1> 	; 01/02/2022
  4106 000040C0 7405                <1> 	jz	short sysstty_19
  4107 000040C2 E9C2000000          <1> 	jmp	sysstty_6
  4108                              <1> sysstty_19:
  4109                              <1> 	; set console tty
  4110                              <1> 	; 29/10/2015
  4111                              <1> 	; 17/01/2014 
  4112 000040C7 80F909              <1> 	cmp	cl, 9
  4113 000040CA 7613                <1> 	jna	short sysstty_0
  4114                              <1> 	; 17/11/2015
  4115 000040CC 80F9FF              <1> 	cmp	cl, 0FFh
  4116 000040CF 7202                <1> 	jb	short sysstty_13
  4117 000040D1 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4118                              <1> sysstty_13:
  4119 000040D3 8A1D[A56F0000]      <1> 	mov	bl, [u.uno] ; process number
  4120 000040D9 8A8B[B76C0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4121                              <1> sysstty_0:
  4122                              <1> 	; 29/06/2015
  4123                              <1> 	;push	dx
  4124                              <1> 	;push	cx
  4125                              <1> 	; 01/02/2022
  4126 000040DF 52                  <1> 	push	edx
  4127 000040E0 51                  <1> 	push	ecx
  4128 000040E1 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4129 000040E3 88C8                <1> 	mov	al, cl
  4130 000040E5 A2[5C6F0000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4131 000040EA E881190000          <1> 	call	ottyp
  4132                              <1> 	; 01/02/2022
  4133 000040EF 59                  <1> 	pop	ecx
  4134 000040F0 5A                  <1> 	pop	edx
  4135                              <1> 	;pop	cx
  4136                              <1> 	;pop	dx
  4137                              <1> 	;
  4138 000040F1 7220                <1> 	jc	short sysstty_pd_err
  4139                              <1> 	;
  4140                              <1> 	; 22/02/2022 (Bug!, BugFix)
  4141                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4142                              <1> 	;
  4143 000040F3 80F908              <1> 	cmp	cl, 8
  4144 000040F6 720C                <1> 	jb	short sysstty_2
  4145                              <1> 	;
  4146 000040F8 80FEFF              <1> 	cmp	dh, 0FFh
  4147 000040FB 7407                <1> 	je	short sysstty_2
  4148                              <1> 		; set communication parameters for serial ports
  4149                              <1> 
  4150                              <1> ; 01/02/2022
  4151                              <1> ;	; 29/10/2015
  4152                              <1> ;	mov	ah, dl ; communication parameters
  4153                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4154                              <1> ;		;			 THRE int + RDA int 
  4155                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4156                              <1> ;		;			 THRE int + RDA int 
  4157                              <1> ;	sub	al, al ; 0
  4158                              <1> ;	; 12/07/2014
  4159                              <1> ;	cmp	cl, 9
  4160                              <1> ;	jb	short sysstty_1
  4161                              <1> ;	inc	al
  4162                              <1> ;sysstty_1:
  4163                              <1> ;	; 01/02/2022
  4164                              <1> ;	push	ecx
  4165                              <1> ;	;push	cx
  4166                              <1> ;	; 29/06/2015	
  4167                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4168                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4169                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4170                              <1> ;	; 01/02/2022
  4171                              <1> ;	pop	ecx	
  4172                              <1> ;	;pop	cx
  4173                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4174                              <1> 
  4175                              <1> 	; 01/02/2022
  4176 000040FD E832010000          <1> 	call	sysstty_scp
  4177 00004102 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4178                              <1> 
  4179                              <1> sysstty_2:
  4180                              <1> 	; 17/01/2014
  4181 00004104 20ED                <1> 	and	ch, ch 	; set cursor position 
  4182                              <1> 			; or comm. parameters ONLY
  4183 00004106 7527                <1> 	jnz	short sysstty_3
  4184                              <1> 	; 01/02/2022
  4185 00004108 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4186 0000410C 7214                <1> 	jb	short sysstty_20
  4187                              <1> 	; clear screen (video page)
  4188 0000410E E93D010000          <1> 	jmp	sysstty_14
  4189                              <1> 
  4190                              <1> sysstty_pd_err: ; 29/06/2015
  4191                              <1> 	; 'permission denied !' error
  4192 00004113 C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4192 0000411B 0000                <1>
  4193 0000411D E9B9F9FFFF          <1> 	jmp	error
  4194                              <1> 
  4195                              <1> sysstty_20:
  4196 00004122 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4197 00004129 888B[B76C0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4198                              <1> sysstty_3:
  4199                              <1> 	; 16/01/2014
  4200 0000412F 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4201                              <1> 	; 17/11/2015
  4202 00004131 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4203 00004133 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4204                              <1> 	;jna	sysstty_9
  4205                              <1> 	; 01/02/2022
  4206 00004135 7705                <1> 	ja	short sysstty_12
  4207 00004137 E9C7000000          <1> 	jmp	sysstty_9
  4208                              <1> 
  4209                              <1> sysstty_12:
  4210                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4211                              <1> 	; (Set specified serial port as console tty port)
  4212                              <1> 	; CH = character to be written
  4213                              <1> 	; 15/04/2014
  4214                              <1> 	; CH = 0 --> initialization only
  4215                              <1> 	; AL = character
  4216                              <1> 	; 26/06/2014
  4217 0000413C 880D[AA6F0000]      <1> 	mov	[u.ttyn], cl
  4218                              <1> 	; 12/07/2014
  4219 00004142 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4220                              <1> 	; 02/02/2022
  4221 00004144 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4222 00004146 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4223 00004148 FEC8                <1> 	dec	al  ; 1 -> 0	
  4224                              <1> 	;and	al, al
  4225 0000414A 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4226                              <1>  	; 04/07/2014
  4227 0000414C E85B1F0000          <1> 	call 	sndc
  4228                              <1> 	; 12/07/2014
  4229 00004151 EB0C                <1> 	jmp	short sysstty_5
  4230                              <1> 
  4231                              <1> sysstty_4:
  4232                              <1> 	; 12/07/2014
  4233                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4234 00004153 88E0                <1> 	mov	al, ah ; 29/06/2015
  4235 00004155 2C08                <1> 	sub	al, 8
  4236                              <1> 	; 27/06/2015
  4237 00004157 E832F4FFFF          <1> 	call	sp_status ; get serial port status
  4238                              <1> 	; AL = Line status, AH = Modem status
  4239                              <1> 	; 12/11/2015
  4240 0000415C 3C80                <1> 	cmp	al, 80h
  4241 0000415E F5                  <1> 	cmc
  4242                              <1> sysstty_5:
  4243 0000415F 66A3[5D6F0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4244                              <1> 		; EAX bits 16-23 = modem status	
  4245 00004165 9C                  <1> 	pushf
  4246 00004166 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4247 00004168 A0[AA6F0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4248 0000416D E8211A0000          <1> 	call	cttyp
  4249 00004172 9D                  <1> 	popf
  4250                              <1> 	;jnc	sysret ; time out error 
  4251                              <1> 	; 01/02/2022
  4252 00004173 7205                <1> 	jc	short sysstty_tmout_err
  4253 00004175 E981F9FFFF          <1> 	jmp	sysret
  4254                              <1> 
  4255                              <1> sysstty_tmout_err:
  4256 0000417A C705[AB6F0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4256 00004182 0000                <1>
  4257 00004184 E952F9FFFF          <1> 	jmp	error
  4258                              <1> 
  4259                              <1> sysstty_6:
  4260                              <1> 	;push	dx
  4261                              <1> 	;push	cx
  4262                              <1> 	; 01/02/2022
  4263 00004189 52                  <1> 	push	edx
  4264 0000418A 51                  <1> 	push	ecx
  4265 0000418B 891D[746F0000]      <1> 	mov	[u.namep], ebx
  4266 00004191 E846080000          <1> 	call	namei
  4267                              <1> 	; 01/02/2022
  4268 00004196 59                  <1> 	pop	ecx
  4269 00004197 5A                  <1> 	pop	edx
  4270                              <1> 	;pop	cx
  4271                              <1> 	;pop	dx
  4272 00004198 725A                <1> 	jc	short sysstty_inv_dn
  4273                              <1> 	;
  4274 0000419A 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4275 0000419E 7754                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4276                              <1> 	;
  4277 000041A0 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4278                              <1> 		       ; /dev/COM1, /dev/COM2
  4279 000041A2 7206                <1> 	jb	short sysstty_7
  4280 000041A4 2C0A                <1> 	sub	al, 10
  4281                              <1> 	; al = 0 to 9
  4282 000041A6 29DB                <1> 	sub	ebx, ebx ; 22/02/2022
  4283 000041A8 EB11                <1> 	jmp	short sysstty_8
  4284                              <1> 
  4285                              <1> sysstty_7:
  4286 000041AA 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4287 000041AC 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4288 000041AE 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4289 000041B5 8A83[B76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4290                              <1> sysstty_8:
  4291                              <1> 	; 22/02/2022
  4292                              <1> 	; (ebx < 256)
  4293 000041BB A2[5C6F0000]        <1> 	mov	[u.r0], al
  4294                              <1> 	; 01/02/2022
  4295                              <1> 	;push	dx
  4296                              <1> 	;push	ax
  4297                              <1> 	;push	cx
  4298 000041C0 52                  <1> 	push	edx
  4299 000041C1 50                  <1> 	push	eax
  4300 000041C2 51                  <1> 	push	ecx
  4301 000041C3 E8A8180000          <1> 	call	ottyp
  4302 000041C8 59                  <1> 	pop	ecx
  4303 000041C9 58                  <1> 	pop	eax
  4304 000041CA 5A                  <1> 	pop	edx
  4305                              <1> 	;pop	cx
  4306                              <1> 	;pop	ax
  4307                              <1> 	;pop	dx
  4308                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4309                              <1> 	; 01/02/2022
  4310 000041CB 7305                <1> 	jnc	short sysstty_21
  4311 000041CD E941FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4312                              <1> sysstty_21:
  4313                              <1> 	; 29/10/2015
  4314 000041D2 86E9                <1> 	xchg 	ch, cl
  4315                              <1> 		; cl = character, ch = color code
  4316 000041D4 86C1                <1> 	xchg	al, cl
  4317                              <1> 		; al = character, cl = tty number
  4318 000041D6 80F907              <1> 	cmp	cl, 7
  4319                              <1> 	;ja	sysstty_12
  4320                              <1> 	; 01/02/2022
  4321 000041D9 7628                <1> 	jna	short sysstty_16
  4322                              <1> ;;
  4323 000041DB 80FEFF              <1> 	cmp	dh, 0FFh
  4324 000041DE 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4325                              <1> 
  4326                              <1> ; 01/02/2022
  4327                              <1> ;	; 29/10/2015
  4328                              <1> ;	mov	ah, dl ; communication parameters
  4329                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4330                              <1> ;		;			 THRE int + RDA int 
  4331                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4332                              <1> ;		;			 THRE int + RDA int 
  4333                              <1> ;	sub	al, al ; 0
  4334                              <1> ;	; 12/07/2014
  4335                              <1> ;	cmp	cl, 9
  4336                              <1> ;	jb	short sysstty_1
  4337                              <1> ;	inc	al
  4338                              <1> ;sysstty_1:
  4339                              <1> ;	; 01/02/2022
  4340                              <1> ;	push	ecx
  4341                              <1> ;	;push	cx
  4342                              <1> ;	; 29/06/2015	
  4343                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4344                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4345                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4346                              <1> ;	; 01/02/2022
  4347                              <1> ;	pop	ecx	
  4348                              <1> ;	;pop	cx
  4349                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4350                              <1> 
  4351                              <1> 	; 02/02/2022
  4352 000041E0 88C5                <1> 	mov	ch, al ; save char
  4353                              <1> 	; 01/02/2022
  4354 000041E2 E84D000000          <1> 	call	sysstty_scp
  4355 000041E7 7291                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4356                              <1> 	; 02/02/2022
  4357 000041E9 88E8                <1> 	mov	al, ch ; restore char
  4358                              <1> sysstty_22:
  4359                              <1> 	; 01/02/2022
  4360 000041EB 08ED                <1> 	or	ch, ch
  4361 000041ED 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4362                              <1> 	; send char to (serial port) terminal
  4363                              <1> 	; al = character
  4364                              <1> 	; cl = tty number (8 or 9)
  4365 000041EF E948FFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4366                              <1> 
  4367                              <1> sysstty_inv_dn: 
  4368                              <1> 	; 27/06/2015
  4369                              <1> 	; Invalid device name (not a tty) ! error
  4370                              <1> 	; (Device is not a tty or device name not found)
  4371 000041F4 C705[AB6F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4371 000041FC 0000                <1>
  4372 000041FE E9D8F8FFFF          <1> 	jmp	error 
  4373                              <1> 
  4374                              <1> sysstty_16:
  4375                              <1> 	; 22/02/2022
  4376                              <1> 	; 16/01/2014
  4377                              <1> 	;xor	bh, bh
  4378                              <1> sysstty_9: 	; tty 0 to tty 7
  4379                              <1> 	; al = character
  4380                              <1> 	; ch = color/attribute ; 01/02/2022
  4381                              <1> 	;
  4382                              <1>  	; 22/02/2022 (BugFix)
  4383                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4384 00004203 29DB                <1> 	sub	ebx, ebx ; *
  4385 00004205 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4386                              <1> 	;
  4387 00004207 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4388 0000420A 7409                <1> 	je	short sysstty_10
  4389                              <1> 	; 02/02/2022
  4390 0000420C 51                  <1> 	push	ecx
  4391 0000420D 50                  <1> 	push	eax
  4392                              <1> 	;push	cx
  4393                              <1> 	;push	ax	
  4394                              <1> 	; 22/02/2022	
  4395                              <1> 	;;movzx	ebx, cl ; *
  4396                              <1> 	;mov	bl, cl ; (tty number = video page number)
  4397 0000420E E8D5D2FFFF          <1> 	call	set_cpos
  4398                              <1> 	;pop	ax
  4399                              <1> 	;pop	cx
  4400                              <1> 	; 02/02/2022
  4401 00004213 58                  <1> 	pop	eax
  4402 00004214 59                  <1> 	pop	ecx
  4403                              <1> sysstty_10: 
  4404                              <1> 	; 29/10/2015
  4405 00004215 08C0                <1> 	or	al, al ; character
  4406 00004217 740D                <1> 	jz      short sysstty_11 ; al = 0
  4407                              <1> 	; 17/11/2015
  4408 00004219 3CFF                <1> 	cmp	al, 0FFh
  4409 0000421B 7309                <1> 	jnb	short sysstty_11
  4410                              <1> 		; ch > 0 and ch < FFh
  4411                              <1> 	; write a character at current cursor position
  4412 0000421D 88EC                <1> 	mov	ah, ch ; color/attribute
  4413                              <1> 	; 12/07/2014
  4414                              <1> 	;push	cx
  4415                              <1> 	; 02/02/2022
  4416 0000421F 51                  <1> 	push	ecx
  4417 00004220 E8AFD3FFFF          <1> 	call	write_c_current
  4418                              <1> 	;pop	cx
  4419                              <1> 	; 02/02/2022
  4420 00004225 59                  <1> 	pop	ecx
  4421                              <1> sysstty_11:
  4422                              <1> 	; 14/01/2014
  4423 00004226 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4424                              <1> 	; 18/01/2014
  4425                              <1> 	;movzx	eax, cl ; 27/06/2015
  4426 00004228 88C8                <1> 	mov	al, cl
  4427 0000422A E864190000          <1> 	call	cttyp
  4428 0000422F E9C7F8FFFF          <1> 	jmp	sysret
  4429                              <1> 
  4430                              <1> sysstty_scp:
  4431                              <1> 	; 02/02/2022
  4432                              <1> 	; set communication parameters (for COM1 or COM2)
  4433                              <1> 	; 01/02/2022
  4434                              <1> 	;
  4435                              <1> 	; 29/10/2015
  4436 00004234 88D4                <1> 	mov	ah, dl ; communication parameters
  4437                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4438                              <1> 		;			 THRE int + RDA int 
  4439                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4440                              <1> 		;			 THRE int + RDA int 
  4441 00004236 28C0                <1> 	sub	al, al ; 0
  4442                              <1> 	; 12/07/2014
  4443 00004238 80F909              <1> 	cmp	cl, 9
  4444 0000423B 7202                <1> 	jb	short sysstty_1
  4445 0000423D FEC0                <1> 	inc	al
  4446                              <1> sysstty_1:
  4447                              <1> 	; 02/02/2022
  4448 0000423F 52                  <1> 	push	edx
  4449                              <1> 	; 01/02/2022
  4450 00004240 51                  <1> 	push	ecx
  4451                              <1> 	;push	cx
  4452                              <1> 	; 29/06/2015	
  4453 00004241 E850F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4454 00004246 66890D[5D6F0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4455                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4456                              <1> 	; 01/02/2022
  4457 0000424D 59                  <1> 	pop	ecx	
  4458                              <1> 	;pop	cx
  4459 0000424E 5A                  <1> 	pop	edx ; 02/02/2022
  4460                              <1> 	; 01/02/2022
  4461                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4462 0000424F C3                  <1> 	retn
  4463                              <1> 
  4464                              <1> sysstty_14:
  4465                              <1> 	; 23/02/2022
  4466                              <1> 	; 02/02/2022
  4467                              <1> 	; ch = 0
  4468                              <1> 	; cl = video page
  4469                              <1> 	;
  4470                              <1> 	; dx = 0FFFFh
  4471                              <1> 	; clear screen (video page)
  4472                              <1> 	;
  4473                              <1> 
  4474                              <1> 	; 02/02/2022
  4475                              <1> 	; clear screen
  4476                              <1> 	;
  4477                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4478                              <1> 
  4479                              <1> 	; 23/02/2022
  4480 00004250 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4481                              <1> 
  4482                              <1> 	; clear video page
  4483 00004252 E810000000          <1> 	call	wttyc ; 23/02/2022
  4484                              <1> 
  4485                              <1> 	; 23/02/2022
  4486 00004257 88D8                <1> 	mov	al, bl
  4487 00004259 8A25[A56F0000]      <1> 	mov	ah, [u.uno]
  4488 0000425F 66A3[5C6F0000]      <1> 	mov	[u.r0], ax
  4489 00004265 EBBF                <1> 	jmp	short sysstty_11
  4490                              <1> 
  4491                              <1> vp_clr:	; 27/02/2022
  4492                              <1> wttyc:
  4493                              <1> 	; 23/02/2022
  4494                              <1> 	; (clear video page)
  4495                              <1> 	; INPUT:
  4496                              <1> 	;  bl = video page (0 to 7)
  4497                              <1> 	;
  4498                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4499                              <1> 
  4500                              <1> 	;xor	dx, dx ; column 0, row 0
  4501                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4502                              <1> 	;
  4503                              <1> ;	movzx	ebx, cl
  4504                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4505                              <1> 
  4506                              <1> ;	shl 	bl, 1 
  4507                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4508                              <1> ;		; AL = lock value (0 or process number)
  4509                              <1> ;	or	al, al
  4510                              <1> ;	jz	short @f
  4511                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4512                              <1> ;	jne	short sysstty_15
  4513                              <1> ;		; only the owner can clear its video page
  4514                              <1> ;	xor	al, al ; 0
  4515                              <1> ;@@:
  4516                              <1> ;	;mov	bl, cl		
  4517                              <1> ;	shr	bl, 1 
  4518                              <1> 
  4519 00004267 30C0                <1> 	xor	al, al	; 0
  4520 00004269 B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4521                              <1> 
  4522                              <1> 	; scroll_up input:
  4523                              <1> 	;
  4524                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4525                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4526                              <1> 	; ah = attribute to be used on blanked line
  4527                              <1> 	; bl = video page number (0 to 7)
  4528                              <1> 
  4529 0000426B E802D3FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4530                              <1> 
  4531                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4532                              <1> 
  4533                              <1> 	; bl = video page number (0 to 7)
  4534                              <1> 	;xor	dx, dx ; column 0, row 0
  4535                              <1> 	; 02/02/2022
  4536 00004270 31D2                <1> 	xor	edx, edx
  4537                              <1> 	; 23/02/2022
  4538                              <1> 	;call	set_cpos
  4539                              <1> 	;retn
  4540 00004272 E971D2FFFF          <1> 	jmp	set_cpos
  4541                              <1> 
  4542                              <1> 	;mov	al, bl
  4543                              <1> 	;mov	ah, [u.uno]
  4544                              <1> 	;mov	[u.r0], ax
  4545                              <1> 	;jmp	short sysstty_11
  4546                              <1> 
  4547                              <1> ;sysstty_15:
  4548                              <1> ;	; 30/01/2022
  4549                              <1> ;	; permission (denied) error
  4550                              <1> ;	;xor	dl, dl ; sysstty call sign
  4551                              <1> ;	mov	al, cl
  4552                              <1> ;	sub	ah, ah ; 0
  4553                              <1> ;	call	cttyp
  4554                              <1> ;	jmp	error
  4555                              <1> 
  4556                              <1> ; Original UNIX v1 'sysstty' routine:
  4557                              <1> ; gtty:
  4558                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4559                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4560                              <1> 	; 		/ r2 has source
  4561                              <1>         ;mov    r2,-(sp)
  4562                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4563                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4564                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4565                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4566                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4567                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4568                              <1>         ;       br .+4 / list empty, skip branch
  4569                              <1>         ;br     1b / get another character until list is empty
  4570                              <1>         ;mov    0b,r1 / move cc offset to r1
  4571                              <1>         ;inc    r1 / bump it for output clist
  4572                              <1>         ;tstb   cc(r1) / is it 0
  4573                              <1>         ;beq    1f / yes, no characters to output
  4574                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4575                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4576                              <1>         ;br     1b / try to calm it down again
  4577                              <1> ;1:
  4578                              <1>         ;mov    (sp)+,r1
  4579                              <1>         ;mov    (sp)+,r2 / restore registers
  4580                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4581                              <1>         ;beq    1f / if 0, 1f
  4582                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4583                              <1>         ;                   / control status register
  4584                              <1> ;1:
  4585                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4586                              <1>         ;beq    1f / if 0 1f
  4587                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4588                              <1> 	;		    / control status reg
  4589                              <1> ;1:
  4590                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4591                              <1>         ;jmp	sysret2 / return to user
  4592                              <1> 
  4593                              <1> sysgtty: ; < get tty status >
  4594                              <1> 	; 22/02/2022
  4595                              <1> 	; 01/02/2022
  4596                              <1> 	; 23/11/2015
  4597                              <1> 	; 29/10/2015
  4598                              <1> 	; 17/10/2015
  4599                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4600                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4601                              <1> 	;
  4602                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4603                              <1> 	; It stores in the three words addressed by it's argument
  4604                              <1> 	; the status of the typewriter whose file descriptor
  4605                              <1> 	; in (u.r0).
  4606                              <1> 	;
  4607                              <1> 	; Calling sequence:
  4608                              <1> 	;	sysgtty; arg
  4609                              <1> 	; Arguments:
  4610                              <1> 	;	arg - address of 3 words destination of the status
  4611                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4612                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4613                              <1> 	; ...............................................................
  4614                              <1> 	;	
  4615                              <1> 	; Retro UNIX 8086 v1 modification: 
  4616                              <1> 	;	'sysgtty' system call will return status of tty
  4617                              <1> 	;	(keyboard, serial port and video page status)
  4618                              <1> 	;	 in following manner:
  4619                              <1> 	;
  4620                              <1> 	; Inputs:
  4621                              <1> 	;	BX = 0 --> means 
  4622                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4623                              <1> 	;	                 for (current) process
  4624                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4625                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4626                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4627                              <1> 	;	     CH > 0 -->	tty number + 1
  4628                              <1> 	;
  4629                              <1> 	;	BX > 0 --> points to name of tty
  4630                              <1> 	;	     CL = 0 --> return keyboard status
  4631                              <1> 	;	     CL = 1 --> return video page status
  4632                              <1> 	;	     CH = undefined		 
  4633                              <1> 	;
  4634                              <1> 	; Outputs:
  4635                              <1> 	;	cf = 0 ->
  4636                              <1> 	;
  4637                              <1> 	;	     AL = tty number from 0 to 9
  4638                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4639                              <1> 	;	     AH = 0 if the tty is free/unused
  4640                              <1> 	;	     AH = the process number of the caller 
  4641                              <1>  	;	     AH = FFh if the tty is locked by another process
  4642                              <1> 	;
  4643                              <1> 	;	  (if calling is for serial port status)
  4644                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4645                              <1> 	;		  (BH = modem status, BL = Line status)
  4646                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4647                              <1> 	;	     CX = 0 (if data is not ready or undefined)
  4648                              <1> 	;
  4649                              <1> 	;	  (if calling is for keyboard status)
  4650                              <1> 	;	     BX = current character in tty/keyboard buffer
  4651                              <1> 	;		  (BH = scan code, BL = ascii code)
  4652                              <1> 	;		  (BX=0 if there is not a waiting character)
  4653                              <1> 	;	     CX  is undefined
  4654                              <1> 	;
  4655                              <1> 	;	  (if calling is for video page status)	
  4656                              <1> 	;	     BX = cursor position on the video page
  4657                              <1> 	;		  if tty number < 8
  4658                              <1> 	;		  (BH = row, BL = column)
  4659                              <1> 	;	     CX = current character (in cursor position)
  4660                              <1> 	;		  on the video page of the tty 
  4661                              <1> 	;		  if tty number < 8
  4662                              <1> 	;		  (CH = color, CL = character)
  4663                              <1> 	;	
  4664                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4665                              <1> 	;
  4666                              <1> 	;	     AH = FFh if the caller is not owner of
  4667                              <1> 	;		  specified tty or console tty
  4668                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4669                              <1> 	;	     BX, CX are undefined if cf = 1
  4670                              <1> 	;
  4671                              <1> 	;	  (If tty number is 8 or 9)
  4672                              <1> 	;	     AL = tty number 
  4673                              <1> 	;	     AH = the process number of the caller 
  4674                              <1> 	;	     BX = serial port status
  4675                              <1> 	;  		 (BH = modem status, BL = Line status)
  4676                              <1> 	;	     CX = 0
  4677                              <1> 	;
  4678                              <1> 		
  4679                              <1> gtty:   ; get (requested) tty number
  4680                              <1> 	; 22/02/2022
  4681                              <1> 	; 01/02/2022
  4682                              <1> 	; 17/10/2015
  4683                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4684                              <1> 	; 30/05/2013 - 12/07/2014
  4685                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4686                              <1> 	;
  4687                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4688                              <1> 	;
  4689                              <1> 	; 28/06/2015 (32 bit modifications)
  4690                              <1> 	; 16/01/2014
  4691 00004277 31C0                <1> 	xor 	eax, eax
  4692 00004279 6648                <1> 	dec	ax ; 17/10/2015
  4693 0000427B A3[5C6F0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4694 00004280 80F901              <1> 	cmp	cl, 1
  4695 00004283 760F                <1> 	jna	short sysgtty_0
  4696                              <1> sysgtty_invp:
  4697                              <1> 	; 28/06/2015
  4698 00004285 C705[AB6F0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4698 0000428D 0000                <1>
  4699 0000428F E947F8FFFF          <1> 	jmp	error
  4700                              <1> sysgtty_0:	
  4701 00004294 21DB                <1> 	and	ebx, ebx
  4702 00004296 742E                <1> 	jz	short sysgtty_1
  4703                              <1> 	;
  4704 00004298 891D[746F0000]      <1> 	mov	[u.namep], ebx
  4705                              <1> 	;push	cx ; 23/11/2015
  4706                              <1> 	; 01/02/2022
  4707 0000429E 51                  <1> 	push	ecx
  4708 0000429F E838070000          <1> 	call	namei
  4709                              <1> 	; 01/02/2022
  4710 000042A4 59                  <1> 	pop	ecx
  4711                              <1> 	;pop	cx ; 23/11/2015
  4712 000042A5 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4713                              <1> 	;
  4714 000042A7 6683F801            <1> 	cmp	ax, 1
  4715 000042AB 7622                <1> 	jna	short sysgtty_2
  4716                              <1> 	; 01/02/2022
  4717 000042AD 20E4                <1> 	and	ah, ah
  4718 000042AF 7506                <1> 	jnz	short sysgtty_inv_dn
  4719                              <1> 	;sub	ax, 10
  4720 000042B1 2C0A                <1> 	sub	al, 10
  4721 000042B3 3C09                <1> 	cmp	al, 9
  4722                              <1> 	;cmp	ax, 9
  4723                              <1> 	;ja	short sysgtty_inv_dn
  4724                              <1> 	;mov	ch, al
  4725                              <1> 	;jmp	short sysgtty_4
  4726                              <1> 	; 23/11/2015
  4727 000042B5 7629                <1> 	jna	short sysgtty_4
  4728                              <1> sysgtty_inv_dn: 
  4729                              <1> 	; 28/06/2015
  4730                              <1> 	; Invalid device name (not a tty) ! error
  4731                              <1> 	; (Device is not a tty or device name not found)
  4732 000042B7 C705[AB6F0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4732 000042BF 0000                <1>
  4733 000042C1 E915F8FFFF          <1> 	jmp	error 
  4734                              <1> sysgtty_1:
  4735                              <1> 	; 16/01/2014
  4736 000042C6 80FD0A              <1> 	cmp	ch, 10
  4737 000042C9 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4738 000042CB FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4739 000042CD 790F                <1> 	jns	short sysgtty_3 ; not negative
  4740                              <1> 	;
  4741                              <1> sysgtty_2:
  4742                              <1> 	; get tty number of console tty
  4743 000042CF 8A25[A56F0000]      <1> 	mov	ah, [u.uno]
  4744                              <1>  	; 28/06/2015
  4745 000042D5 0FB6DC              <1> 	movzx 	ebx, ah
  4746 000042D8 8AAB[B76C0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4747                              <1> sysgtty_3:
  4748 000042DE 88E8                <1> 	mov	al, ch
  4749                              <1> sysgtty_4:
  4750 000042E0 A2[5C6F0000]        <1> 	mov	[u.r0], al
  4751                              <1>  	; 28/06/2015
  4752                              <1> 	;cmp	al, 9
  4753                              <1> 	;ja	short sysgtty_invp
  4754 000042E5 8B2D[586F0000]      <1> 	mov	ebp, [u.usp]
  4755                              <1> 	; 23/11/2015
  4756 000042EB 20C9                <1> 	and	cl, cl
  4757 000042ED 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4758 000042EF 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4759 000042F1 722E                <1> 	jb	short sysgtty_6 ; video page status
  4760                              <1> 	; serial port status
  4761                              <1> 	; 12/07/2014
  4762                              <1> 	;mov	dx, 0
  4763                              <1> 	;je	short sysgtty_5
  4764                              <1> 	;inc	dl
  4765                              <1> ;sysgtty_5:
  4766                              <1> 	; 28/06/2015
  4767 000042F3 2C08                <1> 	sub	al, 8
  4768 000042F5 E894F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4769                              <1> 	; AL = Line status, AH = Modem status
  4770 000042FA 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4771 000042FE 8A25[A56F0000]      <1> 	mov	ah, [u.uno]
  4772 00004304 8825[5D6F0000]      <1>         mov     [u.r0+1], ah
  4773 0000430A 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)	
  4774                              <1> 				; (in ECX)
  4775 00004310 A880                <1> 	test	al, 80h
  4776 00004312 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4777 00004314 A801                <1> 	test	al, 1
  4778                              <1> 	;jz	sysret
  4779 00004316 7404                <1> 	jz	short sysgtty_10 ; 22/02/2022
  4780 00004318 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)	
  4781                              <1> sysgtty_10:
  4782 0000431C E9DAF7FFFF          <1> 	jmp	sysret
  4783                              <1> sysgtty_6:
  4784 00004321 A2[AA6F0000]        <1> 	mov	[u.ttyn], al ; tty number
  4785                              <1> 	;movzx	ebx, al
  4786 00004326 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4787 00004328 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4788                              <1> 	; 22/04/2014 - 29/06/2015
  4789 0000432A 81C3[E46B0000]      <1>         add     ebx, ttyl
  4790 00004330 8A23                <1>  	mov	ah, [ebx]
  4791 00004332 3A25[A56F0000]      <1> 	cmp	ah, [u.uno]
  4792 00004338 7404                <1> 	je	short sysgtty_7
  4793 0000433A 20E4                <1> 	and	ah, ah
  4794                              <1> 	;jz	short sysgtty_7
  4795 0000433C 7506                <1> 	jnz	short sysgtty_8
  4796                              <1> 	;mov	ah, 0FFh
  4797                              <1> sysgtty_7:
  4798 0000433E 8825[5D6F0000]      <1>         mov     [u.r0+1], ah
  4799                              <1> sysgtty_8:
  4800 00004344 08C9                <1> 	or	cl, cl
  4801 00004346 7510                <1> 	jnz	short sysgtty_9
  4802 00004348 B001                <1> 	mov	al, 1  ; test a key is available
  4803 0000434A E8E01C0000          <1> 	call	getc
  4804 0000434F 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4805 00004353 E9A3F7FFFF          <1> 	jmp	sysret
  4806                              <1> sysgtty_9:
  4807 00004358 8A1D[AA6F0000]      <1> 	mov	bl, [u.ttyn]
  4808                              <1> 	; bl = video page number
  4809 0000435E E83D1E0000          <1> 	call 	get_cpos
  4810                              <1> 	; dx = cursor position
  4811 00004363 66895510            <1> 	mov	[ebp+16], dx ; bx
  4812                              <1> 	;mov	bl, [u.ttyn]
  4813                              <1> 	; bl = video page number
  4814 00004367 E8451E0000          <1> 	call	read_ac_current
  4815                              <1> 	; ax = character and attribute/color
  4816 0000436C 66894518            <1> 	mov	[ebp+24], ax ; cx
  4817 00004370 E986F7FFFF          <1> 	jmp	sysret
  4818                              <1> sysgtty_dnr_err:
  4819                              <1> 	; 'device not responding !' error	
  4820                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4821 00004375 C705[AB6F0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ;  25
  4821 0000437D 0000                <1>
  4822 0000437F E957F7FFFF          <1> 	jmp	error	
  4823                              <1> 
  4824                              <1> ; Original UNIX v1 'sysgtty' routine:
  4825                              <1> ; sysgtty:
  4826                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4827                              <1> 	;	       / r2 has destination
  4828                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4829                              <1> 	;                     / in 1st word of dest
  4830                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4831                              <1> 	;                     / in 2nd word of dest
  4832                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4833                              <1>         ;jmp    sysret2 / return to user
  4834                              <1> 	
  4835                              <1> ; Original UNIX v1 'gtty' routine:
  4836                              <1> ; gtty:
  4837                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4838                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4839                              <1>         ;jsr    r0,getf / get the i-number of the file
  4840                              <1>         ;tst    r1 / is it open for reading
  4841                              <1>         ;bgt    1f / yes
  4842                              <1>         ;neg    r1 / no, i-number is negative, 
  4843                              <1> 	;          / so make it positive
  4844                              <1> ;1:
  4845                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4846                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4847                              <1>         ;bhis   error9 / no, error
  4848                              <1>         ;asl    r1 / 0%2
  4849                              <1>         ;asl    r1 / 0%4 / yes
  4850                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4851                              <1> 	;	       ; / tty block
  4852                              <1>         ;mov    u.off,r2 / put argument in r2
  4853                              <1>         ;rts    r0 / return
  2048                                  %include 'u2.s'        ; 11/05/2015
  2049                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS2.INC
  2050                              <1> ; Last Modification: 15/05/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 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2061                              <1> ;
  2062                              <1> ; ****************************************************************************
  2063                              <1> ; 03/01/2016
  2064                              <1> 
  2065                              <1> syslink:
  2066                              <1> 	; 03/02/2022
  2067                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2068                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2069                              <1> 	;
  2070                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2071                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2072                              <1> 	; given to the entry that will go in the current directory.
  2073                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2074                              <1> 	; in the name 2 entry of current directory is the same
  2075                              <1> 	; i-number for the name 1 file.
  2076                              <1> 	;
  2077                              <1> 	; Calling sequence:
  2078                              <1> 	;	syslink; name 1; name 2
  2079                              <1> 	; Arguments:
  2080                              <1> 	;	name 1 - file name to which link will be created.
  2081                              <1> 	;	name 2 - name of entry in current directory that
  2082                              <1> 	;		 links to name 1.
  2083                              <1> 	; Inputs: -
  2084                              <1> 	; Outputs: -
  2085                              <1> 	; ...............................................................
  2086                              <1> 	;	
  2087                              <1> 	; Retro UNIX 8086 v1 modification: 
  2088                              <1> 	;       'syslink' system call has two arguments; so,
  2089                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2090                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2091                              <1> 	;
  2092                              <1> 		; / name1, name2
  2093                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2094 00004384 891D[746F0000]      <1> 	mov	[u.namep], ebx
  2095 0000438A 51                  <1> 	push	ecx
  2096 0000438B E84C060000          <1> 	call	namei
  2097                              <1> 		; jsr r0,namei / find the i-number associated with
  2098                              <1> 			     ; / the 1st path name
  2099                              <1>      	;;and	ax, ax
  2100                              <1> 	;;jz	error ; File not found
  2101                              <1> 	;jc	error 
  2102                              <1> 		; br error9 / cannot be found
  2103 00004390 730F                <1> 	jnc	short syslink0
  2104                              <1> 	;pop 	ecx
  2105                              <1> 	; 'file not found !' error
  2106 00004392 C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2106 0000439A 0000                <1>
  2107 0000439C E93AF7FFFF          <1> 	jmp	error
  2108                              <1> syslink0:
  2109 000043A1 E84B0E0000          <1> 	call	iget
  2110                              <1> 		; jsr r0,iget / get the i-node into core
  2111 000043A6 8F05[746F0000]      <1> 	pop	dword [u.namep] ; ecx
  2112                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2113                              <1> 	; 03/02/2022
  2114 000043AC 50                  <1> 	push	eax
  2115                              <1> 	;push	ax
  2116                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2117                              <1> 			    ; / (a link to this file is to be created)
  2118 000043AD 66FF35[406F0000]    <1> 	push	word [cdev]
  2119                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2120 000043B4 E852000000          <1> 	call	isdir
  2121                              <1> 		; jsr r0,isdir / is it a directory
  2122 000043B9 E81E060000          <1> 	call	namei
  2123                              <1> 		; jsr r0,namei / no, get i-number of name2
  2124                              <1> 	;jnc	error
  2125                              <1> 		; br .+4   / not found 
  2126                              <1> 			 ; / so r1 = i-number of current directory
  2127                              <1> 			 ; / ii = i-number of current directory
  2128                              <1> 		; br error9 / file already exists., error
  2129 000043BE 720F                <1> 	jc	short syslink1
  2130                              <1> 	; pop ax
  2131                              <1> 	; pop ax
  2132                              <1> 	; 'file exists !' error
  2133 000043C0 C705[AB6F0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2133 000043C8 0000                <1>
  2134 000043CA E90CF7FFFF          <1> 	jmp	error
  2135                              <1> syslink1:
  2136 000043CF 6659                <1> 	pop	cx
  2137                              <1> 	;cmp	cx, [cdev]
  2138 000043D1 3A0D[406F0000]      <1> 	cmp	cl, [cdev]
  2139                              <1> 	;jne	error
  2140                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2141                              <1> 			       ; / end of current directory
  2142                              <1> 	        ; bne error9
  2143 000043D7 740F                <1> 	je	short syslink2
  2144                              <1> 	; 'not same drive !' error
  2145 000043D9 C705[AB6F0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2145 000043E1 0000                <1>
  2146 000043E3 E9F3F6FFFF          <1> 	jmp	error
  2147                              <1> syslink2:
  2148                              <1> 	;pop	ax
  2149                              <1> 	;push	ax
  2150                              <1> 	; 03/02/2022
  2151                              <1> 	;mov	eax, [esp]
  2152 000043E8 58                  <1> 	pop	eax
  2153 000043E9 50                  <1> 	push	eax
  2154 000043EA 66A3[8E6F0000]      <1> 	mov	[u.dirbuf], ax
  2155                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2156 000043F0 E89E000000          <1> 	call	mkdir
  2157                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2158                              <1> 		 	     ; / in current directory
  2159                              <1> 	; 03/02/2022
  2160 000043F5 58                  <1> 	pop	eax
  2161                              <1> 	;pop	ax
  2162                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2163 000043F6 E8F60D0000          <1> 	call	iget
  2164                              <1> 		; jsr r0,iget / get i-node into core
  2165 000043FB FE05[5A6C0000]      <1> 	inc	byte [i.nlks]
  2166                              <1> 		; incb i.nlks / add 1 to its number of links
  2167 00004401 E8F50E0000          <1> 	call	setimod
  2168                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2169 00004406 E9F0F6FFFF          <1> 	jmp	sysret
  2170                              <1> 
  2171                              <1> isdir:
  2172                              <1> 	; 03/02/2022
  2173                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2174                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2175                              <1> 	;
  2176                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2177                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2178                              <1> 	;  called by syslink and sysunlink to make sure directories
  2179                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2180                              <1> 	; 'isdir' does not bother checking. The current i-node
  2181                              <1> 	;  is not disturbed.			
  2182                              <1> 	;		
  2183                              <1> 	; INPUTS ->
  2184                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2185                              <1> 	;    u.uid - user id
  2186                              <1> 	; OUTPUTS ->
  2187                              <1> 	;    r1 - contains current i-number upon exit
  2188                              <1> 	;    	 (current i-node back in core) 
  2189                              <1> 	;	
  2190                              <1> 	; ((AX = R1))
  2191                              <1> 	;
  2192                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2193                              <1> 	;
  2194                              <1> 
  2195                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2196                              <1> 	; / there is an error unless super user made the call
  2197                              <1> 	
  2198 0000440B 803D[A26F0000]00    <1> 	cmp	byte [u.uid], 0 
  2199                              <1> 		; tstb u.uid / super user
  2200 00004412 762B                <1> 	jna	short isdir1
  2201                              <1> 		; beq 1f / yes, don't care
  2202 00004414 66FF35[3C6F0000]    <1> 	push	word [ii]
  2203                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2204 0000441B E8D10D0000          <1> 	call	iget
  2205                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2206                              <1> 	; 03/02/2022
  2207 00004420 F605[596C0000]40    <1> 	test	byte [i.flgs+1], 40h
  2208                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2209                              <1> 		; bit $40000,i.flgs / is it a directory
  2210                              <1> 	;jnz	error
  2211                              <1> 		; bne error9 / yes, error
  2212 00004427 740F                <1> 	jz	short isdir0
  2213 00004429 C705[AB6F0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2213 00004431 0000                <1>
  2214                              <1> 				; 'permission denied !' error
  2215                              <1> 	;pop	ax
  2216 00004433 E9A3F6FFFF          <1> 	jmp	error	
  2217                              <1> isdir0:	
  2218 00004438 6658                <1> 	pop	ax
  2219                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2220 0000443A E8B20D0000          <1> 	call	iget
  2221                              <1> 		; jsr r0,iget / get it back in
  2222                              <1> isdir1: ; 1:
  2223 0000443F C3                  <1> 	retn
  2224                              <1> 		; rts r0
  2225                              <1> 
  2226                              <1> sysunlink:
  2227                              <1> 	; 03/02/2022
  2228                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2229                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2230                              <1> 	;
  2231                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2232                              <1> 	; name from its directory. If this entry was the last link
  2233                              <1> 	; to the file, the contents of the file are freed and the
  2234                              <1> 	; file is destroyed. If, however, the file was open in any
  2235                              <1> 	; process, the actual destruction is delayed until it is 
  2236                              <1> 	; closed, even though the directory entry has disappeared.
  2237                              <1> 	; 
  2238                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2239                              <1> 	; does not exist or that its directory can not be written.
  2240                              <1> 	; Write permission is not required on the file itself.
  2241                              <1> 	; It is also illegal to unlink a directory (except for
  2242                              <1> 	; the superuser).
  2243                              <1> 	;
  2244                              <1> 	; Calling sequence:
  2245                              <1> 	;	sysunlink; name
  2246                              <1> 	; Arguments:
  2247                              <1> 	;	name - name of directory entry to be removed 
  2248                              <1> 	; Inputs: -
  2249                              <1> 	; Outputs: -
  2250                              <1> 	; ...............................................................
  2251                              <1> 	;				
  2252                              <1> 	; Retro UNIX 8086 v1 modification:
  2253                              <1> 	;	 The user/application program puts address of the name
  2254                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2255                              <1> 
  2256                              <1> 	; / name - remove link name
  2257 00004440 891D[746F0000]      <1> 	mov	[u.namep], ebx
  2258                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2259 00004446 E891050000          <1> 	call	namei
  2260                              <1> 		; jsr r0,namei / find the i-number associated 
  2261                              <1> 			     ; / with the path name
  2262                              <1> 	;jc	error
  2263                              <1> 		; br error9 / not found
  2264 0000444B 730F                <1> 	jnc	short sysunlink1
  2265                              <1> 	; 'file not found !' error
  2266 0000444D C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2266 00004455 0000                <1>
  2267 00004457 E97FF6FFFF          <1> 	jmp	error
  2268                              <1> sysunlink1:
  2269                              <1> 	; 03/02/2022
  2270 0000445C 50                  <1> 	push	eax
  2271                              <1> 	;push	ax
  2272                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2273 0000445D E8A9FFFFFF          <1> 	call	isdir
  2274                              <1> 		; jsr r0,isdir / is it a directory
  2275                              <1> 	;xor 	ax, ax
  2276                              <1> 	; 03/02/2022
  2277 00004462 31C0                <1> 	xor	eax, eax
  2278 00004464 66A3[8E6F0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2279                              <1> 		; clr u.dirbuf / no, clear the location that will
  2280                              <1> 			   ; / get written into the i-number portion
  2281                              <1> 			 ; / of the entry
  2282 0000446A 832D[786F0000]0A    <1> 	sub	dword [u.off], 10
  2283                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2284 00004471 E865000000          <1> 	call	wdir
  2285                              <1> 		; jsr r0,wdir / free the directory entry
  2286                              <1> 	; 03/02/2022
  2287 00004476 58                  <1> 	pop	eax
  2288                              <1> 	;pop	ax
  2289                              <1> 		; mov (sp)+,r1 / get i-number back
  2290 00004477 E8750D0000          <1> 	call	iget
  2291                              <1> 		; jsr r0,iget / get i-node
  2292 0000447C E87A0E0000          <1> 	call	setimod
  2293                              <1> 		; jsr r0,setimod / set modified flag
  2294 00004481 FE0D[5A6C0000]      <1> 	dec	byte [i.nlks]
  2295                              <1> 		; decb i.nlks / decrement the number of links
  2296                              <1> 	;jnz	sysret
  2297                              <1> 		; bgt sysret9 / if this was not the last link
  2298                              <1> 			    ; / to file return
  2299                              <1> 	; 03/02/2022
  2300 00004487 7505                <1> 	jnz	short sysunlink2
  2301                              <1> 	; AX = r1 = i-number
  2302 00004489 E8B8090000          <1> 	call	anyi
  2303                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2304                              <1> 			 ; / Then free contents of file and destroy it.
  2305                              <1> sysunlink2:
  2306 0000448E E968F6FFFF          <1> 	jmp	sysret
  2307                              <1> 		; br sysret9
  2308                              <1> 
  2309                              <1> mkdir:
  2310                              <1> 	; 03/02/2022
  2311                              <1> 	; 12/10/2015
  2312                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2313                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2314                              <1> 	;
  2315                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2316                              <1> 	; by u.namep into the current directory.
  2317                              <1> 	;
  2318                              <1> 	; INPUTS ->
  2319                              <1> 	;    u.namep - points to a file name 
  2320                              <1> 	;	           that is about to be a directory entry.
  2321                              <1> 	;    ii - current directory's i-number.	
  2322                              <1> 	; OUTPUTS ->
  2323                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2324                              <1> 	;    u.off - points to entry to be filled 
  2325                              <1> 	;	     in the current directory		
  2326                              <1> 	;    u.base - points to start of u.dirbuf.
  2327                              <1> 	;    r1 - contains i-number of current directory 
  2328                              <1> 	;	
  2329                              <1> 	; ((AX = R1)) output
  2330                              <1> 	;
  2331                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2332                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2333                              <1> 	;
  2334                              <1> 
  2335                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2336 00004493 31C0                <1> 	xor 	eax, eax
  2337 00004495 BF[906F0000]        <1>         mov     edi, u.dirbuf+2
  2338 0000449A 89FE                <1> 	mov	esi, edi
  2339 0000449C AB                  <1> 	stosd
  2340 0000449D AB                  <1> 	stosd
  2341                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2342 0000449E 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2343                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2344                              <1> 	;mov 	ebp, [u.namep]
  2345 000044A0 E8B9060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2346                              <1> 		; esi = physical address (page start + offset)
  2347                              <1> 		; ecx = byte count in the page (1 - 4096)
  2348                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2349                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2350                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2351                              <1> mkdir_1: ; 1: 
  2352 000044A5 45                  <1> 	inc	ebp ; 12/10/2015
  2353                              <1> 	;
  2354                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2355                              <1> 	 ; 01/08/2013
  2356 000044A6 AC                  <1> 	lodsb
  2357                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2358 000044A7 20C0                <1> 	and 	al, al
  2359 000044A9 7426                <1> 	jz 	short mkdir_3 	  
  2360                              <1> 		; beq 1f / if null, done
  2361 000044AB 3C2F                <1> 	cmp	al, '/'
  2362                              <1> 		; cmp r1,$'/ / is it a "/"?
  2363 000044AD 7413                <1> 	je	short mkdir_err
  2364                              <1> 	;je	error
  2365                              <1> 		; beq error9 / yes, error
  2366                              <1> 	; 03/02/2022
  2367 000044AF 49                  <1> 	dec	ecx
  2368                              <1> 	; 12/10/2015
  2369                              <1> 	;dec	cx
  2370 000044B0 7505                <1> 	jnz	short mkdir_2
  2371                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2372 000044B2 E8AD060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2373                              <1> 		; esi = physical address (page start + offset)
  2374                              <1> 		; ecx = byte count in the page
  2375                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2376                              <1> mkdir_2:
  2377 000044B7 81FF[986F0000]      <1> 	cmp     edi, u.dirbuf+10
  2378                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2379                              <1> 				     ; / a char?
  2380 000044BD 74E6                <1> 	je	short mkdir_1
  2381                              <1> 		; beq 1b / yes, go back
  2382 000044BF AA                  <1> 	stosb
  2383                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2384 000044C0 EBE3                <1> 	jmp 	short mkdir_1
  2385                              <1> 		; br 1b / get next char
  2386                              <1> mkdir_err:
  2387                              <1> 	; 17/06/2015
  2388 000044C2 C705[AB6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2388 000044CA 0000                <1>
  2389 000044CC E90AF6FFFF          <1> 	jmp	error
  2390                              <1> mkdir_3: ; 1:
  2391 000044D1 A1[706F0000]        <1> 	mov	eax, [u.dirp]
  2392 000044D6 A3[786F0000]        <1> 	mov	[u.off], eax
  2393                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2394                              <1> 				 ; / slot to u.off
  2395                              <1> wdir: 	; 03/02/2022
  2396                              <1> 	; 29/04/2013
  2397 000044DB C705[7C6F0000]-     <1>         mov     dword [u.base], u.dirbuf
  2397 000044E1 [8E6F0000]          <1>
  2398                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2399 000044E5 C705[806F0000]0A00- <1>         mov     dword [u.count], 10
  2399 000044ED 0000                <1>
  2400                              <1> 		; mov $10.,u.count / u.count = 10
  2401 000044EF 66A1[3C6F0000]      <1> 	mov	ax, [ii] 
  2402                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2403 000044F5 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2404 000044F7 E8C90D0000          <1> 	call 	access
  2405                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2406                              <1> 				 ; / for writing
  2407                              <1> 	; AX = i-number of current directory
  2408                              <1> 	; 01/08/2013
  2409 000044FC FE05[BD6F0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2410                              <1> 	;call	writei
  2411                              <1> 	;	; jsr r0,writei / write into directory
  2412                              <1> 	;retn	
  2413                              <1> 	;	; rts r0
  2414                              <1> 	; 03/02/2022
  2415 00004502 E9AC100000          <1> 	jmp	writei
  2416                              <1> 
  2417                              <1> sysexec:
  2418                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2419                              <1> 	; 03/02/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.18)
  2420                              <1> 	; 23/10/2015
  2421                              <1> 	; 19/10/2015
  2422                              <1> 	; 10/10/2015, 18/10/2015
  2423                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2424                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2425                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2426                              <1> 	; 24/06/2015, 25/06/2015
  2427                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2428                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2429                              <1> 	;
  2430                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2431                              <1> 	; pointed to by 'name' in the sysexec call. 
  2432                              <1> 	; 'sysexec' performs the following operations:
  2433                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2434                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2435                              <1> 	;    3. sets trap vectors to system routines.
  2436                              <1> 	;    4. loads arguments to be passed to executing file into
  2437                              <1> 	;	highest locations of user's core
  2438                              <1> 	;    5. puts pointers to arguments in locations immediately
  2439                              <1> 	;	following arguments.
  2440                              <1> 	;    6.	saves number of arguments in next location.
  2441                              <1> 	;    7. intializes user's stack area so that all registers
  2442                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2443                              <1> 	;	to core when 'sysret' restores registers 
  2444                              <1> 	;	and does an rti.
  2445                              <1> 	;    8. inializes u.r0 and u.sp
  2446                              <1> 	;    9. zeros user's core down to u.r0
  2447                              <1> 	;   10.	reads executable file from storage device into core
  2448                              <1> 	;	starting at location 'core'.
  2449                              <1> 	;   11.	sets u.break to point to end of user's code with
  2450                              <1> 	;	data area appended.
  2451                              <1> 	;   12.	calls 'sysret' which returns control at location
  2452                              <1> 	;	'core' via 'rti' instruction. 		  		
  2453                              <1> 	;
  2454                              <1> 	; Calling sequence:
  2455                              <1> 	;	sysexec; namep; argp
  2456                              <1> 	; Arguments:
  2457                              <1> 	;	namep - points to pathname of file to be executed
  2458                              <1> 	;	argp  - address of table of argument pointers
  2459                              <1> 	;	argp1... argpn - table of argument pointers
  2460                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2461                              <1> 	; Inputs: (arguments)
  2462                              <1> 	; Outputs: -	
  2463                              <1> 	; ...............................................................
  2464                              <1> 	;
  2465                              <1> 	; Retro UNIX 386 v1 modification: 
  2466                              <1> 	;	User application runs in it's own virtual space 
  2467                              <1> 	;	which is izolated from kernel memory (and other
  2468                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2469                              <1> 	;	privilige mode. Virtual start address is always 0.
  2470                              <1> 	;	User's core memory starts at linear address 400000h
  2471                              <1> 	;	(the end of the 1st 4MB).
  2472                              <1> 	;
  2473                              <1> 	; Retro UNIX 8086 v1 modification: 
  2474                              <1> 	;	user/application segment and system/kernel segment
  2475                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2476                              <1> 	;	are different (user's registers are saved to 
  2477                              <1> 	;	and then restored from system's stack.)
  2478                              <1> 	;
  2479                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2480                              <1> 	;	      arguments which were in these registers;
  2481                              <1> 	;	      but, it returns by putting the 1st argument
  2482                              <1> 	;	      in 'u.namep' and the 2nd argument
  2483                              <1> 	;	      on top of stack. (1st argument is offset of the
  2484                              <1> 	;	      file/path name in the user's program segment.)		 	
  2485                              <1> 	
  2486                              <1> 	;call	arg2
  2487                              <1> 	; * name - 'u.namep' points to address of file/path name
  2488                              <1> 	;          in the user's program segment ('u.segmnt')
  2489                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2490                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2491                              <1> 	;          which is on top of stack.
  2492                              <1> 	;
  2493                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2494                              <1> 
  2495                              <1> 	; 23/06/2015 (32 bit modifications)
  2496                              <1> 
  2497 00004507 891D[746F0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2498                              <1>         ; 18/10/2015
  2499 0000450D 890D[D46F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2500 00004513 E8C4040000          <1> 	call	namei
  2501                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2502                              <1> 			     ; / named in sysexec call in r1
  2503                              <1> 	;jc	error
  2504                              <1> 		; br error9
  2505 00004518 731E                <1> 	jnc	short sysexec_0
  2506                              <1> 	;
  2507                              <1> 	; 'file not found !' error
  2508 0000451A C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2508 00004522 0000                <1>
  2509 00004524 E9B2F5FFFF          <1> 	jmp	error 
  2510                              <1> sysexec_not_exf:
  2511                              <1> 	; 'not executable file !' error
  2512 00004529 C705[AB6F0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2512 00004531 0000                <1>
  2513 00004533 E9A3F5FFFF          <1> 	jmp	error 
  2514                              <1> sysexec_0:
  2515 00004538 E8B40C0000          <1> 	call	iget
  2516                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2517                              <1> 	; 03/02/2022
  2518 0000453D F605[586C0000]10    <1> 	test	byte [i.flgs], 10h
  2519                              <1>         ;test	word [i.flgs], 10h
  2520                              <1> 		; bit $20,i.flgs / is file executable
  2521 00004544 74E3                <1> 	jz	short sysexec_not_exf
  2522                              <1> 	;jz	error
  2523                              <1> 		; beq error9
  2524                              <1> 	;;
  2525 00004546 E88B140000          <1> 	call	iopen
  2526                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2527                              <1> 			     ; / given in r1 (opens file)
  2528                              <1> 	; AX = i-number of the file
  2529                              <1> 	; 03/02/2022
  2530 0000454B F605[586C0000]20    <1> 	test	byte [i.flgs], 20h
  2531                              <1> 	;test	word [i.flgs], 20h
  2532                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2533 00004552 7415                <1> 	jz	short sysexec_1
  2534                              <1> 		; beq 1f
  2535 00004554 803D[A26F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2536                              <1> 		; tstb u.uid / test user id
  2537 0000455B 760C                <1> 	jna	short sysexec_1
  2538                              <1> 		; beq 1f / super user
  2539 0000455D 8A0D[5B6C0000]      <1> 	mov	cl, [i.uid]
  2540 00004563 880D[A26F0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2541                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2542                              <1> 				 ; / as process user id
  2543                              <1> sysexec_1:
  2544                              <1> 	; 03/02/2022
  2545                              <1> 	; 18/10/2215
  2546                              <1> 	; 10/10/2015
  2547                              <1> 	; 21/07/2015, 24/07/2015
  2548                              <1> 	; 24/06/2015, 25/06/2015
  2549                              <1>         ; Moving arguments to the end of [u.upage]
  2550                              <1> 	; (by regarding page borders in user's memory space)
  2551                              <1> 	;
  2552                              <1> 	; 10/10/2015
  2553                              <1> 	; 21/07/2015
  2554 00004569 89E5                <1> 	mov	ebp, esp ; (**)
  2555                              <1> 	; 18/10/2015
  2556 0000456B 89EF                <1> 	mov 	edi, ebp
  2557 0000456D B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2558                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2559 00004572 29CF                <1> 	sub	edi, ecx
  2560 00004574 89FC                <1> 	mov	esp, edi
  2561 00004576 31C0                <1> 	xor	eax, eax
  2562 00004578 A3[846F0000]        <1> 	mov 	[u.nread], eax ; 0
  2563                              <1> 	; 03/02/2022
  2564                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2565                              <1> 	; may leave it with any value after an error))
  2566                              <1> 	;mov	[argc], ax
  2567 0000457D A2[D26F0000]        <1> 	mov	[argc], al ; 0
  2568                              <1> 	;
  2569 00004582 49                  <1> 	dec	ecx ; 256 - 1
  2570 00004583 890D[806F0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2571                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2572                              <1> sysexec_2:
  2573 00004589 8B35[D46F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2574 0000458F E864020000          <1> 	call	get_argp
  2575                              <1> 	;mov	ecx, 4 
  2576                              <1> 	; 03/02/2022
  2577 00004594 31C9                <1> 	xor	ecx, ecx
  2578 00004596 B104                <1> 	mov	cl, 4
  2579                              <1> sysexec_3:
  2580 00004598 21C0                <1> 	and	eax, eax
  2581 0000459A 7456                <1> 	jz	short sysexec_6
  2582                              <1> 	; 18/10/2015
  2583 0000459C 010D[D46F0000]      <1> 	add	[argv], ecx ; 4
  2584 000045A2 66FF05[D26F0000]    <1> 	inc	word [argc]
  2585                              <1> 	;
  2586 000045A9 A3[7C6F0000]        <1> 	mov	[u.base], eax
  2587                              <1>  	; 23/10/2015
  2588 000045AE 66C705[BB6F0000]00- <1> 	mov	word [u.pcount], 0
  2588 000045B6 00                  <1>
  2589                              <1> sysexec_4:
  2590 000045B7 E8AC110000          <1> 	call	cpass ; get a character from user's core memory
  2591 000045BC 750B                <1>         jnz	short sysexec_5
  2592                              <1> 		; (max. 255 chars + null)
  2593                              <1> 	; 18/10/2015
  2594 000045BE 28C0                <1> 	sub 	al, al
  2595 000045C0 AA                  <1> 	stosb
  2596 000045C1 FF05[846F0000]      <1> 	inc	dword [u.nread]
  2597 000045C7 EB29                <1> 	jmp	short sysexec_6
  2598                              <1> sysexec_5:
  2599 000045C9 AA                  <1> 	stosb
  2600 000045CA 20C0                <1> 	and 	al, al
  2601 000045CC 75E9                <1> 	jnz	short sysexec_4
  2602                              <1> 	;mov	ecx, 4
  2603                              <1> 	; 03/02/2022
  2604 000045CE 29C9                <1> 	sub	ecx, ecx
  2605 000045D0 B104                <1> 	mov	cl, 4
  2606                              <1> 	;cmp	[ncount], ecx ; 4
  2607                              <1> 	; 03/02/2022
  2608 000045D2 66390D[D06F0000]    <1> 	cmp	[ncount], cx ; 4
  2609 000045D9 72AE                <1> 	jb	short sysexec_2
  2610 000045DB 8B35[CC6F0000]      <1> 	mov	esi, [nbase]
  2611 000045E1 010D[CC6F0000]      <1> 	add	[nbase], ecx ; 4	
  2612 000045E7 66290D[D06F0000]    <1> 	sub	[ncount], cx 
  2613 000045EE 8B06                <1> 	mov	eax, [esi]
  2614 000045F0 EBA6                <1> 	jmp	short sysexec_3
  2615                              <1> sysexec_6:
  2616                              <1> 	; 18/10/2015
  2617                              <1> 	; argument list transfer from user's core memory to
  2618                              <1> 	; kernel stack frame is OK here.
  2619                              <1> 	; [u.nread] = ; argument list length
  2620                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2621                              <1> 	;
  2622                              <1> 	; 18/10/2015
  2623                              <1>         ; 21/07/2015, 24/07/2015
  2624                              <1> 	; 25/06/2015, 02/07/2015
  2625                              <1> 	; 23/06/2015, 24/06/2015
  2626                              <1> 	;
  2627 000045F2 8B1D[B36F0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2628 000045F8 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2629 000045FA 740A                <1> 	jz	short sysexec_7
  2630 000045FC A1[AF6F0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2631 00004601 E8FEE8FFFF          <1> 	call	deallocate_page_dir
  2632                              <1> sysexec_7:
  2633 00004606 E82EE8FFFF          <1> 	call	make_page_dir
  2634                              <1> 	;jc	short sysexec_14
  2635                              <1> 	;jc	panic  ; allocation error 
  2636                              <1> 		       ; after a deallocation would be nonsence !?
  2637                              <1> 	; 03/02/2022
  2638 0000460B 7243                <1> 	jc	short sysexec_panic
  2639                              <1> 
  2640                              <1> 	; 24/07/2015
  2641                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2642                              <1> 	;     of the user's page directory
  2643                              <1> 	;     (It is needed for interrupts!)
  2644                              <1> 	; 18/10/2015
  2645 0000460D 8B15[986B0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2646 00004613 8B02                <1> 	mov	eax, [edx] ; physical address of
  2647                              <1> 			   ; kernel's first page table (1st 4 MB)
  2648                              <1> 			   ; (PDE 0 of kernel's page directory)
  2649 00004615 8B15[AF6F0000]      <1> 	mov 	edx, [u.pgdir]
  2650 0000461B 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2651                              <1> 	;
  2652                              <1> 	; 20/07/2015
  2653 0000461D BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2654                              <1> 	; 18/10/2015
  2655 00004622 BE[C46F0000]        <1> 	mov	esi, pcore ; physical start address
  2656                              <1> sysexec_8:	
  2657 00004627 B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2658 0000462C E826E8FFFF          <1> 	call	make_page_table
  2659                              <1> 	;jc	panic
  2660                              <1> 	; 03/02/2022
  2661 00004631 721D                <1> 	jc	short sysexec_panic
  2662                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2663 00004633 E82DE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2664                              <1> 	;jc	panic
  2665                              <1> 	; 03/02/2022
  2666 00004638 7216                <1> 	jc	short sysexec_panic
  2667                              <1> 	;
  2668 0000463A 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2669                              <1> 	; ebx = virtual address (24/07/2015)
  2670                              <1> 	; 03/02/2022
  2671                              <1> 	;call 	add_to_swap_queue
  2672                              <1> 	; 18/10/2015
  2673 0000463C 81FE[C86F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2674 00004642 7411                <1> 	je	short sysexec_9 ; yes
  2675 00004644 BE[C86F0000]        <1> 	mov	esi, ecore ; physical address of the last page 
  2676                              <1> 	; 20/07/2015
  2677 00004649 BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2678                              <1> 	; ebx = virtual end address + segment base address - 4K
  2679 0000464E EBD7                <1>         jmp     short sysexec_8
  2680                              <1> 
  2681                              <1> sysexec_panic:
  2682                              <1> 	; 03/02/2022
  2683 00004650 E945EDFFFF          <1> 	jmp	panic
  2684                              <1> 
  2685                              <1> sysexec_9:
  2686                              <1> 	; 18/10/2015
  2687                              <1> 	; 26/08/2015
  2688                              <1> 	; 25/06/2015
  2689                              <1> 	; move arguments from kernel stack to [ecore]
  2690                              <1> 	; (argument list/line will be copied from kernel stack
  2691                              <1> 	; frame to the last (stack) page of user's core memory)
  2692                              <1> 	; 18/10/2015
  2693 00004655 8B3D[C86F0000]      <1> 	mov	edi, [ecore]
  2694 0000465B 81C700100000        <1> 	add	edi, PAGE_SIZE
  2695                              <1> 	;movzx	eax, word [argc]
  2696                              <1> 	; 03/02/2022
  2697 00004661 31C0                <1> 	xor	eax, eax
  2698 00004663 A0[D26F0000]        <1> 	mov	al, [argc]
  2699 00004668 08C0                <1> 	or	al, al
  2700                              <1> 	;or	eax, eax
  2701 0000466A 7509                <1> 	jnz	short sysexec_10
  2702 0000466C 89FB                <1> 	mov 	ebx, edi
  2703 0000466E 83EB04              <1> 	sub	ebx, 4 
  2704 00004671 8903                <1> 	mov	[ebx], eax ; 0
  2705 00004673 EB43                <1> 	jmp 	short sysexec_13
  2706                              <1> sysexec_10:
  2707 00004675 8B0D[846F0000]      <1> 	mov	ecx, [u.nread]
  2708                              <1> 	;mov 	esi, [argv]
  2709 0000467B 89E6                <1> 	mov	esi, esp ; start address of argument list
  2710 0000467D 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2711                              <1> 	
  2712                              <1> 	;;;;
  2713                              <1> 	; 09/05/2022
  2714                              <1> 	; (move edi -backward- to dword boundary)
  2715                              <1> 	; ((this will prevent 'general protection fault' error
  2716                              <1> 	;  as result of a lodsd or dword move instruction
  2717                              <1> 	;  at the end of argument list))
  2718 0000467F 83EF03              <1> 	sub	edi, 3
  2719 00004682 83E7FC              <1> 	and	edi, ~3 ; (*)
  2720                              <1> 	;;;
  2721                              <1> 
  2722 00004685 89C2                <1> 	mov	edx, eax
  2723                              <1> 	; 03/02/2022 ; ([argc] < 32)
  2724 00004687 FEC2                <1> 	inc	dl ; argument count + 1 for argc value
  2725 00004689 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2726                              <1> 	; edx <= 128
  2727 0000468C 89FB                <1> 	mov	ebx, edi
  2728                              <1> 	; 09/05/2022 (*) - edi is already dword aligned -
  2729                              <1> 	;and	bl, 0FCh ; 32 bit (dword) alignment
  2730 0000468E 29D3                <1> 	sub 	ebx, edx
  2731 00004690 89FA                <1> 	mov	edx, edi
  2732 00004692 F3A4                <1> 	rep	movsb
  2733 00004694 89D6                <1> 	mov 	esi, edx
  2734 00004696 89DF                <1> 	mov 	edi, ebx
  2735 00004698 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2736 0000469D 2B15[C86F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2737 000046A3 AB                  <1> 	stosd	; eax = argument count	
  2738                              <1> sysexec_11:
  2739 000046A4 89F0                <1> 	mov	eax, esi
  2740 000046A6 01D0                <1> 	add	eax, edx
  2741 000046A8 AB                  <1> 	stosd  ; eax = virtual address
  2742 000046A9 FE0D[D26F0000]      <1> 	dec	byte [argc]
  2743 000046AF 7407                <1> 	jz	short sysexec_13
  2744                              <1> sysexec_12:
  2745 000046B1 AC                  <1> 	lodsb
  2746 000046B2 20C0                <1> 	and	al, al
  2747 000046B4 75FB                <1> 	jnz	short sysexec_12
  2748 000046B6 EBEC                <1> 	jmp	short sysexec_11
  2749                              <1> 	;
  2750                              <1> 	; 1:
  2751                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2752                              <1> 			     ; / pointers to arguments to be passed
  2753                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2754                              <1> 			      ; / u.quit = 1 take quit
  2755                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2756                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2757                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2758                              <1> 			       ; / system routine
  2759                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2760                              <1> 			       ; / set to take system routine
  2761                              <1> 		; mov $sstack,sp / stack space used during swapping
  2762                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2763                              <1> 		; mov $ecore,r5 / r5 has end of core
  2764                              <1> 		; mov $core,r4 / r4 has start of users core
  2765                              <1> 		; mov r4,u.base / u.base has start of users core
  2766                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2767                              <1> 	; 1:
  2768                              <1> 		; tst (r2)+ / argument char = "nul"
  2769                              <1> 		; bne 1b
  2770                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2771                              <1> 			  ; / end of argument pointer list
  2772                              <1> 	; 1:
  2773                              <1> 	     ; / move arguments to bottom of users core
  2774                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2775                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2776                              <1> 			    ; / ptr list
  2777                              <1> 		; blo 1f / branch to 1f when all arguments
  2778                              <1> 		       ; / are moved
  2779                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2780                              <1> 	; 2:
  2781                              <1> 		; tstb (r3)+
  2782                              <1> 		; bne 2b / scan argument for \0 (nul)
  2783                              <1> 
  2784                              <1> 	; 2:
  2785                              <1> 		; movb -(r3),-(r5) / move argument char 
  2786                              <1> 				 ; / by char starting at "ecore"
  2787                              <1> 		; cmp r3,(r2) / moved all characters in 
  2788                              <1> 			    ; / this argument
  2789                              <1> 		; bhi 2b / branch 2b if not
  2790                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2791                              <1> 			     ; / r5 has pointer to nth arg
  2792                              <1> 		; br 1b / string
  2793                              <1> 	; 1:
  2794                              <1> 		; clrb -(r5)
  2795                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2796                              <1> 			 ; / last word of argument strings
  2797                              <1> 		; mov $core,r2
  2798                              <1> 	
  2799                              <1> 	; 1: / move argument pointers into core following 
  2800                              <1> 	      ; / argument strings
  2801                              <1> 		; cmp r2,r4
  2802                              <1> 		; bhis 1f / branch to 1f when all pointers
  2803                              <1> 			; / are moved
  2804                              <1> 		; mov (r2)+,-(r5)
  2805                              <1> 		; br 1b
  2806                              <1> 	; 1:
  2807                              <1> 		; sub $core,r4 / gives number of arguments *2
  2808                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2809                              <1> 		       ; / the number of args stored
  2810                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2811                              <1> 			     ; / of the argument pointers
  2812                              <1> sysexec_13:
  2813                              <1> 	; 19/10/2015
  2814                              <1> 	; 18/10/2015
  2815                              <1> 	; 29/07/2015
  2816                              <1> 	; 24/07/2015, 25/07/2015
  2817                              <1> 	; 25/06/2015, 20/07/2015
  2818                              <1> 	; 23/06/2015, 24/06/2015
  2819                              <1> 	;
  2820                              <1> 	; moving arguments to [ecore] is OK here..
  2821                              <1> 	; 18/10/2015
  2822 000046B8 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2823                              <1> 	; ebx = beginning addres of argument list pointers
  2824                              <1> 	;	in user's stack
  2825                              <1> 	; 19/10/2015
  2826 000046BA 2B1D[C86F0000]      <1> 	sub 	ebx, [ecore]
  2827 000046C0 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2828                              <1> 			; end of core - 4096 (last page)
  2829                              <1> 			; (virtual address)
  2830 000046C6 891D[D46F0000]      <1> 	mov	[argv], ebx
  2831 000046CC 891D[886F0000]      <1> 	mov	[u.break], ebx ; available user memory
  2832                              <1> 	;
  2833 000046D2 29C0                <1> 	sub	eax, eax
  2834 000046D4 C705[806F0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2834 000046DC 0000                <1>
  2835                              <1> 		; mov $14,u.count
  2836 000046DE C705[6C6F0000]-     <1> 	mov	dword [u.fofp], u.off
  2836 000046E4 [786F0000]          <1>
  2837                              <1> 		; mov $u.off,u.fofp
  2838 000046E8 A3[786F0000]        <1> 	mov	[u.off], eax ; 0
  2839                              <1> 		; clr u.off / set offset in file to be read to zero
  2840                              <1> 	; 25/07/2015
  2841 000046ED A3[7C6F0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2842                              <1> 	; 25/06/2015 
  2843 000046F2 66A1[3C6F0000]      <1> 	mov	ax, [ii]
  2844                              <1> 	; AX = i-number of the executable file
  2845 000046F8 E8C80C0000          <1> 	call	readi
  2846                              <1> 		; jsr r0,readi / read in first six words of 
  2847                              <1> 			; / user's file, starting at $core
  2848                              <1> 		; mov sp,r5 / put users stack address in r5
  2849                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2850                              <1> 				; / from r5 (leaves number of words
  2851                              <1> 				; / less 26 available for
  2852                              <1> 			     	; / program in user core
  2853                              <1> 		; mov r5,u.count /
  2854                              <1> 	; 25/06/2015
  2855 000046FD 8B0D[886F0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2856 00004703 890D[806F0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2857                              <1> 	;
  2858 00004709 8B0D[846F0000]      <1> 	mov	ecx, [u.nread]
  2859 0000470F 890D[886F0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2860 00004715 80F920              <1> 	cmp	cl, 32
  2861 00004718 7540                <1>         jne     short sysexec_15
  2862                              <1> 	;:
  2863                              <1> 	; 25/06/2015
  2864                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2865                              <1> 	; 18/10/2015
  2866 0000471A 8B35[C46F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2867                              <1> 		             ; (phys. start addr. of the exec. file)
  2868 00004720 AD                  <1> 	lodsd
  2869 00004721 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2870 00004725 7533                <1> 	jne	short sysexec_15
  2871                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2872                              <1> 			      ; / if file is standard a.out format
  2873                              <1> 		; bne 1f / branch, if not standard format
  2874 00004727 AD                  <1> 	lodsd
  2875 00004728 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2876 0000472A AD                  <1> 	lodsd
  2877 0000472B 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2878                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2879                              <1> 		              ; / number of bytes in program text	
  2880                              <1> 		; sub $14,r5 / subtract 12
  2881 0000472D 89CB                <1> 	mov	ebx, ecx
  2882                              <1> 	;
  2883                              <1> 	; 25/06/2015
  2884                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2885                              <1> 	;	and SINGLIX operating systems (as code template).
  2886                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2887                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2888                              <1> 	;	Overrun is not possible for current version. 	
  2889                              <1> 	;
  2890 0000472F AD                  <1> 	lodsd	
  2891 00004730 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2892 00004732 3B1D[806F0000]      <1> 	cmp	ebx, [u.count]
  2893 00004738 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2894                              <1> 	;
  2895                              <1> 	; 24/07/2015
  2896                              <1> 	; add bss section size to [u.break]
  2897 0000473A 0105[886F0000]      <1> 	add 	[u.break], eax
  2898                              <1> 	;
  2899 00004740 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2900                              <1> 	;cmp	ecx, [u.count]
  2901                              <1> 	;jnb	short sysexec_16
  2902                              <1> 		; cmp r5,u.count /
  2903                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2904 00004743 890D[806F0000]      <1> 	mov	[u.count], ecx ; required read count
  2905                              <1> 		; mov r5,u.count
  2906                              <1> 	;
  2907 00004749 EB2A                <1> 	jmp	short sysexec_16
  2908                              <1> 	;
  2909                              <1> sysexec_14:
  2910                              <1> 	; 23/06/2015
  2911                              <1> 	; insufficient (out of) memory
  2912 0000474B C705[AB6F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2912 00004753 0000                <1>
  2913 00004755 E981F3FFFF          <1> 	jmp	error
  2914                              <1> 	;
  2915                              <1> sysexec_15:
  2916                              <1> 	; 25/06/2015
  2917 0000475A 0FB715[5C6C0000]    <1>         movzx   edx, word [i.size] ; file size
  2918 00004761 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2919 00004763 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2920 00004765 01D1                <1> 	add	ecx, edx ; [i.size]
  2921 00004767 3B0D[806F0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2922 0000476D 77DC                <1> 	ja	short sysexec_14
  2923 0000476F 8915[806F0000]      <1> 	mov	[u.count], edx
  2924                              <1> sysexec_16:
  2925 00004775 66A1[3C6F0000]      <1> 	mov	ax, [ii] ; i-number
  2926 0000477B E8450C0000          <1> 	call	readi
  2927                              <1> 		; add core+10,u.nread / add size of user data area 
  2928                              <1> 		                    ; / to u.nread
  2929                              <1> 		; br 2f
  2930                              <1> 	; 1:
  2931                              <1> 		; jsr r0,readi / read in rest of file
  2932                              <1> 	; 2:
  2933 00004780 8B0D[846F0000]      <1> 	mov	ecx, [u.nread]
  2934 00004786 010D[886F0000]      <1> 	add	[u.break], ecx
  2935                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2936                              <1> 				    ; / user code
  2937                              <1> 		; add $core+14,u.break / plus data area
  2938                              <1> sysexec_17: ; 20/07/2015
  2939                              <1> 	; 03/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2940                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2941                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2942                              <1> 	;;mov	ax, [ii] ; i-number
  2943                              <1> 	;call	iclose
  2944                              <1> 	;	; jsr r0,iclose / does nothing
  2945 0000478C 31C0                <1>         xor     eax, eax
  2946 0000478E FEC0                <1> 	inc	al
  2947 00004790 66A3[9A6F0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2948 00004796 66A3[9C6F0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2949                              <1> 	; 02/07/2015
  2950 0000479C 833D[B36F0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  2951 000047A3 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  2952                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  2953 000047A5 8B15[986B0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  2954 000047AB 8915[B36F0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  2955                              <1> sysexec_18:
  2956                              <1> 	; 18/10/2015
  2957                              <1> 	; 05/08/2015
  2958                              <1> 	; 29/07/2015
  2959 000047B1 8B2D[D46F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  2960                              <1> 			    ; list pointers (argument count)
  2961 000047B7 FA                  <1> 	cli
  2962 000047B8 8B25[346B0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  2963                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  2964                              <1> 			    ; for this process	 
  2965                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  2966                              <1> 	;xor	eax, eax ; 0
  2967 000047BE FEC8                <1> 	dec	al ; eax = 0
  2968 000047C0 66BA2300            <1> 	mov	dx, UDATA
  2969 000047C4 6652                <1> 	push	dx  ; user's stack segment
  2970 000047C6 55                  <1> 	push	ebp ; user's stack pointer
  2971                              <1> 		    ; (points to number of arguments)
  2972 000047C7 FB                  <1> 	sti
  2973 000047C8 9C                  <1> 	pushfd	; EFLAGS
  2974                              <1> 		; Set IF for enabling interrupts in user mode	
  2975                              <1> 	;or	dword [esp], 200h 
  2976                              <1> 	;
  2977                              <1> 	;mov	bx, UCODE
  2978                              <1> 	;push	bx ; user's code segment
  2979 000047C9 6A1B                <1> 	push	UCODE
  2980                              <1> 	;push	0
  2981 000047CB 50                  <1> 	push	eax ; EIP (=0) - start address -	
  2982                              <1> 		; clr -(r5) / popped into ps when rti in 
  2983                              <1> 			  ; / sysrele is executed
  2984                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  2985                              <1> 		                ; / in sysrele is executed
  2986                              <1> 		;mov r5,0f / load second copyz argument
  2987                              <1> 		;tst -(r5) / decrement r5
  2988 000047CC 8925[546F0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  2989                              <1> 	; 05/08/2015
  2990                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  2991                              <1> 	; ('push dx' would cause to general protection fault, 
  2992                              <1> 	; after 'pop ds' etc.)
  2993                              <1> 	;
  2994                              <1> 	;; push dx ; ds (UDATA)
  2995                              <1> 	;; push dx ; es (UDATA)
  2996                              <1> 	;; push dx ; fs (UDATA)
  2997                              <1> 	;; push dx ; gs (UDATA)
  2998                              <1> 	;
  2999                              <1> 	; This is a trick to prevent general protection fault
  3000                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3001 000047D2 8EC2                <1> 	mov 	es, dx ; UDATA
  3002 000047D4 06                  <1> 	push 	es ; ds (UDATA)
  3003 000047D5 06                  <1> 	push 	es ; es (UDATA)
  3004 000047D6 06                  <1> 	push 	es ; fs (UDATA)
  3005 000047D7 06                  <1> 	push	es ; gs (UDATA)
  3006 000047D8 66BA1000            <1> 	mov	dx, KDATA
  3007 000047DC 8EC2                <1> 	mov	es, dx
  3008                              <1> 	;
  3009                              <1> 	;; pushad simulation
  3010 000047DE 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3011 000047E0 50                  <1> 	push	eax ; eax (0)
  3012 000047E1 50                  <1> 	push	eax ; ecx (0)
  3013 000047E2 50                  <1> 	push	eax ; edx (0)
  3014 000047E3 50                  <1> 	push	eax ; ebx (0)
  3015 000047E4 55                  <1> 	push	ebp ; esp before pushad
  3016 000047E5 50                  <1> 	push	eax ; ebp (0)
  3017 000047E6 50                  <1> 	push	eax ; esi (0)		
  3018 000047E7 50                  <1> 	push	eax ; edi (0)	
  3019                              <1> 	;
  3020 000047E8 A3[5C6F0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3021 000047ED 8925[586F0000]      <1> 	mov	[u.usp], esp
  3022                              <1> 		; mov r5,u.r0 /
  3023                              <1> 		; sub $16.,r5 / skip 8 words
  3024                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3025                              <1> 		;             / effectively zeroes all regs
  3026                              <1> 			    ; / when sysrele is executed
  3027                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3028                              <1> 		; clr u.break
  3029                              <1> 		; mov r5,sp / point sp to user's stack
  3030                              <1> 	;
  3031 000047F3 E905F3FFFF          <1> 	jmp	sysret0
  3032                              <1> 	;jmp	sysret
  3033                              <1> 		; br sysret3 / return to core image at $core
  3034                              <1> 
  3035                              <1> get_argp:
  3036                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  3037                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3038                              <1> 	; 18/10/2015 (nbase, ncount)
  3039                              <1> 	; 21/07/2015
  3040                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3041                              <1> 	; Get (virtual) address of argument from user's core memory
  3042                              <1> 	;
  3043                              <1> 	; INPUT:
  3044                              <1> 	;	esi = virtual address of argument pointer
  3045                              <1> 	; OUTPUT:
  3046                              <1> 	;	eax = virtual address of argument
  3047                              <1> 	;
  3048                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3049                              <1> 	;
  3050 000047F8 833D[B36F0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3051                              <1> 				    ; (the caller is kernel)
  3052                              <1>         ;jna	short get_argpk
  3053                              <1> 	; 03/02/2022
  3054 000047FF 7719                <1> 	ja	short get_argp5
  3055                              <1> get_argpk:
  3056                              <1> 	; Argument is in kernel's memory space
  3057 00004801 66C705[D06F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3057 00004809 10                  <1>
  3058 0000480A 8935[CC6F0000]      <1> 	mov	[nbase], esi
  3059 00004810 8305[CC6F0000]04    <1> 	add	dword [nbase], 4
  3060 00004817 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3061 00004819 C3                  <1> 	retn
  3062                              <1> get_argp5:
  3063 0000481A 89F3                <1>      	mov	ebx, esi
  3064 0000481C E89FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3065 00004821 7257                <1>         jc	short get_argp_err ; 03/02/2022 (short jump)
  3066 00004823 A3[CC6F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3067 00004828 66890D[D06F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3068 0000482F B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3069                              <1> 	;cmp	cx, ax ; 4
  3070                              <1> 	; 03/02/2022
  3071 00004834 39C1                <1> 	cmp	ecx, eax
  3072 00004836 734C                <1> 	jnb	short get_argp2
  3073 00004838 89F3                <1> 	mov	ebx, esi
  3074 0000483A 01CB                <1> 	add	ebx, ecx
  3075 0000483C E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3076 00004841 7237                <1> 	jc	short get_argp_err
  3077                              <1> 	;push	esi
  3078 00004843 89C6                <1> 	mov	esi, eax
  3079 00004845 66870D[D06F0000]    <1> 	xchg	cx, [ncount]
  3080 0000484C 8735[CC6F0000]      <1> 	xchg	esi, [nbase]
  3081 00004852 B504                <1> 	mov	ch, 4
  3082 00004854 28CD                <1> 	sub	ch, cl
  3083                              <1> get_argp0:
  3084 00004856 AC                  <1> 	lodsb
  3085                              <1> 	;push	ax
  3086                              <1> 	; 03/02/2022
  3087 00004857 50                  <1> 	push	eax
  3088 00004858 FEC9                <1> 	dec	cl
  3089 0000485A 75FA                <1>         jnz     short get_argp0
  3090 0000485C 8B35[CC6F0000]      <1> 	mov	esi, [nbase]
  3091                              <1> 	; 21/07/2015
  3092 00004862 0FB6C5              <1> 	movzx	eax, ch
  3093 00004865 0105[CC6F0000]      <1> 	add	[nbase], eax
  3094 0000486B 662905[D06F0000]    <1> 	sub	[ncount], ax
  3095                              <1> get_argp1:
  3096 00004872 AC                  <1> 	lodsb
  3097 00004873 FECD                <1> 	dec	ch
  3098 00004875 7423                <1>         jz      short get_argp3
  3099                              <1>         ;push	ax
  3100                              <1> 	; 03/02/2022
  3101 00004877 50                  <1> 	push	eax
  3102 00004878 EBF8                <1> 	jmp     short get_argp1
  3103                              <1> get_argp_err:
  3104 0000487A A3[AB6F0000]        <1> 	mov	[u.error], eax
  3105 0000487F E957F2FFFF          <1> 	jmp	error
  3106                              <1> get_argp2:
  3107                              <1> 	; 21/07/2015
  3108                              <1> 	;mov	eax, 4
  3109 00004884 8B15[CC6F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3110 0000488A 0105[CC6F0000]      <1> 	add	[nbase], eax
  3111 00004890 662905[D06F0000]    <1> 	sub	[ncount], ax
  3112                              <1> 	;
  3113 00004897 8B02                <1> 	mov	eax, [edx]
  3114 00004899 C3                  <1> 	retn
  3115                              <1> get_argp3:
  3116 0000489A B103                <1> 	mov	cl, 3
  3117                              <1> get_argp4:
  3118 0000489C C1E008              <1> 	shl	eax, 8
  3119                              <1> 	;pop	dx
  3120                              <1> 	; 03/02/2022
  3121 0000489F 5A                  <1> 	pop	edx
  3122 000048A0 88D0                <1> 	mov 	al, dl
  3123 000048A2 E2F8                <1>         loop    get_argp4
  3124                              <1> 	;pop	esi
  3125 000048A4 C3                  <1> 	retn	
  3126                              <1> 
  3127                              <1> sysfstat:
  3128                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3129                              <1> 	;	([idev] return in eax)
  3130                              <1> 	;	0 = root device
  3131                              <1> 	;	1 = mounted device (>0)
  3132                              <1> 	; 03/02/2022
  3133                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3134                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3135                              <1> 	;
  3136                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3137                              <1> 	; on open files instead of files given by name. It puts the
  3138                              <1> 	; buffer address on the stack, gets the i-number and
  3139                              <1> 	; checks to see if the file is open for reading or writing.
  3140                              <1> 	; If the file is open for writing (i-number is negative)
  3141                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3142                              <1> 	; is made.	
  3143                              <1> 	;
  3144                              <1> 	; Calling sequence:
  3145                              <1> 	;	sysfstat; buf
  3146                              <1> 	; Arguments:
  3147                              <1> 	;	buf - buffer address
  3148                              <1> 	;
  3149                              <1> 	; Inputs: *u.r0 - file descriptor
  3150                              <1> 	; Outputs: buffer is loaded with file information
  3151                              <1> 	; ...............................................................
  3152                              <1> 	;				
  3153                              <1> 	; Retro UNIX 8086 v1 modification:
  3154                              <1> 	;       'sysfstat' system call has two arguments; so,
  3155                              <1> 	;	* 1st argument, file descriptor is in BX register
  3156                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3157                              <1> 
  3158                              <1> 	; / set status of open file
  3159                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3160 000048A5 51                  <1> 	push	ecx
  3161                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3162                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3163                              <1> 		; jsr r0,getf / get the files i-number
  3164                              <1> 	; BX = file descriptor (file number)
  3165 000048A6 E8FE000000          <1> 	call	getf1
  3166                              <1> 	; 03/02/2022
  3167 000048AB 21C0                <1> 	and	eax, eax
  3168                              <1> 	;and	ax, ax ; i-number of the file
  3169                              <1> 		; tst	r1 / is it 0?
  3170                              <1> 	;jz	error
  3171                              <1> 		; beq error3 / yes, error
  3172 000048AD 750F                <1> 	jnz	short sysfstat1
  3173 000048AF C705[AB6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3173 000048B7 0000                <1>
  3174 000048B9 E91DF2FFFF          <1> 	jmp	error
  3175                              <1> sysfstat1:
  3176 000048BE 80FC80              <1> 	cmp	ah, 80h
  3177 000048C1 7222                <1>         jb      short sysstat1
  3178                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3179 000048C3 66F7D8              <1> 	neg	ax
  3180                              <1> 		; neg r1 / make it positive, then branch
  3181 000048C6 EB1D                <1> 	jmp	short sysstat1
  3182                              <1> 		; br 1f / to 1f
  3183                              <1> sysstat:
  3184                              <1> 	; 09/05/2022 (Retro UNIX 386 v1, Kernel v0.2.0.19)
  3185                              <1> 	;	([idev] return in eax)
  3186                              <1> 	;	0 = root device
  3187                              <1> 	;	1 = mounted device (>0)
  3188                              <1> 	; 03/02/2022
  3189                              <1> 	; 18/10/2015
  3190                              <1> 	; 07/10/2015
  3191                              <1> 	; 02/09/2015
  3192                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3193                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3194                              <1> 	;
  3195                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3196                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3197                              <1> 	; long and information about the file placed in it.	
  3198                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3199                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3200                              <1> 	; is then loaded and the results are given in the UNIX
  3201                              <1> 	; Programmers Manual sysstat (II).	
  3202                              <1> 	;
  3203                              <1> 	; Calling sequence:
  3204                              <1> 	;	sysstat; name; buf
  3205                              <1> 	; Arguments:
  3206                              <1> 	;	name - points to the name of the file
  3207                              <1> 	;	buf - address of a 34 bytes buffer
  3208                              <1> 	; Inputs: -
  3209                              <1> 	; Outputs: buffer is loaded with file information
  3210                              <1> 	; ...............................................................
  3211                              <1> 	;				
  3212                              <1> 	; Retro UNIX 8086 v1 modification: 
  3213                              <1> 	;       'sysstat' system call has two arguments; so,
  3214                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3215                              <1> 	;	to get sysstat system call arguments from the user;
  3216                              <1> 	;	* 1st argument, name is pointed to by BX register
  3217                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3218                              <1> 	;
  3219                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3220                              <1> 	;	      arguments which were in these registers;
  3221                              <1> 	;	      but, it returns by putting the 1st argument
  3222                              <1> 	;	      in 'u.namep' and the 2nd argument
  3223                              <1> 	;	      on top of stack. (1st argument is offset of the
  3224                              <1> 	;	      file/path name in the user's program segment.)		 	
  3225                              <1> 	
  3226                              <1> 	; / ; name of file; buffer - get files status
  3227                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3228 000048C8 891D[746F0000]      <1> 	mov	[u.namep], ebx
  3229 000048CE 51                  <1> 	push	ecx
  3230 000048CF E808010000          <1> 	call	namei
  3231                              <1> 		; jsr r0,namei / get the i-number for the file
  3232                              <1> 	;jc	error
  3233                              <1> 		; br error3 / no such file, error
  3234 000048D4 730F                <1> 	jnc	short sysstat1
  3235                              <1> 	; pop 	ecx
  3236                              <1> sysstat_err0:
  3237                              <1> 	; 'file not found !' error
  3238 000048D6 C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3238 000048DE 0000                <1>
  3239 000048E0 E9F6F1FFFF          <1> 	jmp	error
  3240                              <1> 
  3241                              <1> ;statx: db 0
  3242                              <1> 
  3243                              <1> sysstat1: ; 1:
  3244 000048E5 E807090000          <1> 	call	iget
  3245                              <1> 		; jsr r0,iget / get the i-node into core
  3246                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3247                              <1> 	; 02/09/2015
  3248 000048EA 8F05[7C6F0000]      <1> 	pop	dword [u.base]
  3249                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3250 000048F0 E861000000          <1> 	call	sysstat_gpa ; get physical address
  3251 000048F5 730A                <1> 	jnc 	short sysstat2
  3252                              <1> sysstat_err1:
  3253 000048F7 A3[AB6F0000]        <1> 	mov	dword [u.error], eax ; error code
  3254 000048FC E9DAF1FFFF          <1> 	jmp	error
  3255                              <1> sysstat2:
  3256 00004901 A0[3C6F0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3257 00004906 AA                  <1> 	stosb
  3258 00004907 FF05[7C6F0000]      <1> 	inc 	dword [u.base]
  3259                              <1> 	;dec 	cx
  3260                              <1> 	; 03/02/2022
  3261 0000490D 49                  <1> 	dec	ecx
  3262 0000490E 7505                <1> 	jnz	short sysstat3
  3263 00004910 E841000000          <1> 	call	sysstat_gpa
  3264                              <1> 	;jc	short sysstat_err1
  3265                              <1> sysstat3:
  3266 00004915 A0[3D6F0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3267 0000491A AA                  <1> 	stosb
  3268                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3269 0000491B FF05[7C6F0000]      <1> 	inc 	dword [u.base]
  3270                              <1> 	;;dec 	word [u.pcount]
  3271                              <1> 	;dec	cx
  3272                              <1> 	; 03/02/2022
  3273 00004921 49                  <1> 	dec	ecx
  3274 00004922 7505                <1> 	jnz	short sysstat4
  3275 00004924 E82D000000          <1> 	call	sysstat_gpa
  3276                              <1> 	;jc	short sysstat_err1	
  3277                              <1> sysstat4:
  3278 00004929 BE[586C0000]        <1> 	mov	esi, inode
  3279                              <1> 		; mov $inode,r2 / r2 points to i-node
  3280                              <1> sysstat5: ; 1:
  3281 0000492E A4                  <1> 	movsb
  3282                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3283 0000492F FF05[7C6F0000]      <1> 	inc 	dword [u.base]
  3284                              <1> 	;;dec 	word [u.pcount]
  3285                              <1> 	;dec	cx
  3286                              <1> 	; 03/02/2022
  3287 00004935 49                  <1> 	dec	ecx
  3288 00004936 7505                <1> 	jnz	short sysstat6
  3289 00004938 E819000000          <1> 	call	sysstat_gpa
  3290                              <1> 	;jc	short sysstat_err1
  3291                              <1> sysstat6:		
  3292 0000493D 81FE[786C0000]      <1> 	cmp	esi, inode + 32
  3293                              <1> 		; cmp r2,$inode+32 / done?
  3294 00004943 75E9                <1> 	jne	short sysstat5
  3295                              <1> 		; bne 1b / no, go back
  3296                              <1> 
  3297                              <1> 	;;;
  3298                              <1> 	; 09/05/2022
  3299                              <1> 	;*** additional feature *** -retro unix only- 
  3300                              <1> 	;
  3301                              <1> 	; !! return device number -of current inode- in eax !!
  3302                              <1> 	;
  3303                              <1> 	; (modification reason/purpose:
  3304                              <1> 	; to improve 'pwd' command's pathname output/result
  3305                              <1> 	; and to correct 'cp' command's 'can not copy file itself'
  3306                              <1> 	; error due to same inode numbers in root file system
  3307                              <1> 	; and mounted file system.)
  3308                              <1> 	;
  3309 00004945 29C0                <1> 	sub	eax, eax
  3310 00004947 A0[3E6F0000]        <1> 	mov	al, [idev] ; [cdev]
  3311 0000494C A3[5C6F0000]        <1> 	mov	[u.r0], eax
  3312                              <1> 	;;;  
  3313                              <1> 
  3314 00004951 E9A5F1FFFF          <1> 	jmp	sysret
  3315                              <1> 		; br sysret3 / return through sysret
  3316                              <1> 	;
  3317                              <1> sysstat_gpa: ; get physical address of file status buffer
  3318                              <1> 	; 02/09/2015
  3319 00004956 8B1D[7C6F0000]      <1> 	mov 	ebx, [u.base]
  3320                              <1> 	; 07/10/2015
  3321 0000495C E85FE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3322                              <1> 	;jc	short sysstat_gpa1
  3323 00004961 7294                <1> 	jc	short sysstat_err1
  3324                              <1> 	; 18/10/2015
  3325 00004963 89C7                <1> 	mov	edi, eax ; physical address
  3326                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3327                              <1> ;sysstat_gpa1:
  3328 00004965 C3                  <1> 	retn
  3329                              <1> 
  3330                              <1> fclose:
  3331                              <1> 	; 03/02/2022
  3332                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3333                              <1> 	;            (32 bit offset pointer modification)
  3334                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3335                              <1> 	;
  3336                              <1> 	; Given the file descriptor (index to the u.fp list)
  3337                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3338                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3339                              <1> 	; u.fp list is cleared. If all the processes that opened
  3340                              <1> 	; that file close it, then fsp etry is freed and the file
  3341                              <1> 	; is closed. If not a return is taken. 
  3342                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3343                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3344                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3345                              <1> 	; a check is made to see if the file is special.	
  3346                              <1> 	;
  3347                              <1> 	; INPUTS ->
  3348                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3349                              <1> 	;    u.fp - list of entries in the fsp table
  3350                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3351                              <1> 	; OUTPUTS ->
  3352                              <1> 	;    r1 - contains the same file descriptor
  3353                              <1> 	;    r2 - contains i-number
  3354                              <1> 	;
  3355                              <1> 	; ((AX = R1))
  3356                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3357                              <1> 	;
  3358                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3359                              <1> 	;              if i-number of the file is 0. (error)  	
  3360                              <1> 
  3361                              <1> 	;movzx	edx, ax ; **
  3362                              <1> 	; 03/02/2022
  3363                              <1> 	;movzx	edx, al
  3364 00004966 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 03/02/2022
  3365 00004968 50                  <1> 	push	eax ; ***
  3366                              <1> 	;push	ax ; ***
  3367                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3368                              <1> 			     ; / the index to u.fp list)
  3369 00004969 E839000000          <1> 	call	getf
  3370                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3371                              <1> 			    ; / cdev has device =, u.fofp 
  3372                              <1> 			    ; / points to 3rd word of fsp entry
  3373 0000496E 6683F801            <1> 	cmp	ax, 1 ; r1
  3374                              <1> 		; tst r1 / is i-number 0?
  3375 00004972 7231                <1> 	jb	short fclose_2
  3376                              <1> 		; beq 1f / yes, i-node not active so return
  3377                              <1> 		; tst (r0)+ / no, jump over error return
  3378 00004974 89D3                <1> 	mov	ebx, edx ; **
  3379                              <1> 	; 03/02/2022
  3380 00004976 89C2                <1> 	mov	edx, eax ; *
  3381                              <1> 	;mov 	dx, ax ; *
  3382                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3383                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3384                              <1> 			    ; / which is index to u.fp ; **
  3385 00004978 C683[626F0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3386                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3387 0000497F 8B1D[6C6F0000]      <1> 	mov	ebx, [u.fofp]
  3388                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3389                              <1> fclose_0:
  3390 00004985 FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3391                              <1> 		; decb 2(r1) / decrement the number of processes 
  3392                              <1> 			   ; / that have opened the file
  3393 00004988 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3394                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3395                              <1> 	;
  3396                              <1> 	; 03/02/2022
  3397 0000498A 52                  <1> 	push	edx ; *
  3398                              <1> 	;push	dx ; *
  3399                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3400                              <1> 	;xor	ax, ax ; 0
  3401                              <1> 	; 03/02/2022
  3402 0000498B 31C0                <1> 	xor	eax, eax
  3403 0000498D 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3404                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3405 00004991 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3406                              <1> 		; tstb	3(r1) / has this file been deleted
  3407 00004994 20C0                <1> 	and	al, al
  3408 00004996 7407                <1> 	jz	short fclose_1
  3409                              <1> 		; beq 2f / no, branch
  3410                              <1> 	; 03/02/2022
  3411 00004998 89D0                <1> 	mov	eax, edx
  3412                              <1> 	;mov	ax, dx ; *
  3413                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3414                              <1> 	; AX = inode number
  3415 0000499A E8A7040000          <1> 	call	anyi
  3416                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3417                              <1> 			    ; / check if file appears in fsp again
  3418                              <1> fclose_1: ; 2:
  3419                              <1> 	; 03/02/2022
  3420 0000499F 58                  <1> 	pop	eax ; * 
  3421                              <1> 	;pop	ax ; *
  3422                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3423 000049A0 E870110000          <1> 	call	iclose ; close if it is special file 
  3424                              <1> 		; jsr r0,iclose / check to see if its a special file
  3425                              <1> fclose_2: ; 1:
  3426                              <1> 	; 03/02/2022
  3427 000049A5 58                  <1> 	pop	eax ; ***
  3428                              <1> 	;pop	ax ; ***
  3429                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3430 000049A6 C3                  <1> 	retn
  3431                              <1> 		; rts r0
  3432                              <1> 
  3433                              <1> getf:	; / get the device number and the i-number of an open file
  3434                              <1> 	; 03/02/2022
  3435                              <1> 	; 13/05/2015
  3436                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3437                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3438                              <1> 	;
  3439 000049A7 89C3                <1> 	mov	ebx, eax
  3440                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3441                              <1> 	; 03/02/2022
  3442 000049A9 29C0                <1> 	sub	eax, eax
  3443                              <1> 	;
  3444 000049AB 83FB0A              <1> 	cmp	ebx, 10
  3445                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3446 000049AE 732B                <1>         jnb	short getf2 ; 13/05/2015
  3447                              <1> 	;jnb	error
  3448                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3449                              <1> 			    ; / index in fsp table
  3450                              <1> 	; 03/02/2022
  3451 000049B0 8A83[626F0000]      <1> 	mov	al, [ebx+u.fp]
  3452                              <1> 	;mov	bl, [ebx+u.fp]
  3453                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3454                              <1> 		                  ; / in fsp table
  3455                              <1> 	; 03/02/2022
  3456 000049B6 08C0                <1> 	or	al, al
  3457 000049B8 7421                <1> 	jz	short getf2
  3458                              <1> 	;or	bl, bl
  3459                              <1> 	;jnz	short getf3
  3460                              <1> 	;;jz	short getf4
  3461                              <1> 		; beq 1f / if its zero return
  3462                              <1> ;getf2:
  3463                              <1> ;	; 'File not open !' error (ax=0)
  3464                              <1> ;	sub	eax, eax
  3465                              <1> ;	retn
  3466                              <1> 
  3467                              <1> getf3:	
  3468                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3469                              <1> 	;
  3470                              <1> 	; 'fsp' table (10 bytes/entry)
  3471                              <1> 	; bit 15				   bit 0
  3472                              <1> 	; ---|-------------------------------------------
  3473                              <1> 	; r/w|		i-number of open file
  3474                              <1> 	; ---|-------------------------------------------
  3475                              <1> 	;		   device number
  3476                              <1> 	; -----------------------------------------------
  3477                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3478                              <1> 	; -----------------------------------------------
  3479                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3480                              <1> 	; ----------------------|------------------------
  3481                              <1> 	;  flag that says file 	| number of processes
  3482                              <1> 	;   has been deleted	| that have file open 
  3483                              <1> 	; ----------------------|------------------------
  3484                              <1> 	;
  3485                              <1> 	;mov	eax, 10
  3486                              <1> 	; 03/02/2022
  3487 000049BA B30A                <1> 	mov	bl, 10
  3488 000049BC F6E3                <1> 	mul	bl
  3489 000049BE BB[226D0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3490 000049C3 01C3                <1> 	add	ebx, eax
  3491                              <1> 		; asl r1
  3492                              <1> 		; asl r1 / multiply by 8 to get index into 
  3493                              <1> 		       ; / fsp table entry
  3494                              <1> 		; asl r1
  3495                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3496                              <1> 			      ; / in the fsp entry
  3497 000049C5 891D[6C6F0000]      <1> 	mov	[u.fofp], ebx
  3498                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3499                              <1> 			      ; / in fsp entry in u.fofp
  3500 000049CB 4B                  <1> 	dec	ebx
  3501 000049CC 4B                  <1> 	dec	ebx
  3502                              <1> 	;mov	al, [ebx]
  3503 000049CD 668B03              <1> 	mov	ax, [ebx]
  3504                              <1> 	;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3505 000049D0 66A3[406F0000]      <1> 	mov	[cdev], ax ; ;;in fact (!) 
  3506                              <1> 			     ;;dev number is in 1 byte
  3507                              <1> 		; mov -(r1),cdev / remove the device number  cdev
  3508 000049D6 4B                  <1> 	dec	ebx
  3509 000049D7 4B                  <1> 	dec	ebx
  3510 000049D8 668B03              <1> 	mov	ax, [ebx]
  3511                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3512                              <1> getf2:	; 03/02/2022
  3513                              <1> getf4:	; 1:
  3514 000049DB C3                  <1> 	retn
  3515                              <1> 		; rts r0
  3516                              <1> 
  3517                              <1> namei:
  3518                              <1> 	; 15/05/2022
  3519                              <1> 	; 14/05/2022 (mounted directory path, '..' method)
  3520                              <1> 	; 03/02/2022
  3521                              <1> 	; 18/10/2015 (nbase, ncount)
  3522                              <1> 	; 12/10/2015
  3523                              <1> 	; 21/08/2015
  3524                              <1> 	; 18/07/2015
  3525                              <1> 	; 02/07/2015
  3526                              <1> 	; 17/06/2015
  3527                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3528                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3529                              <1> 	;
  3530                              <1> 	; 'namei' takes a file path name and returns i-number of
  3531                              <1> 	; the file in the current directory or the root directory
  3532                              <1> 	; (if the first character of the pathname is '/').	
  3533                              <1> 	;
  3534                              <1> 	; INPUTS ->
  3535                              <1> 	;    u.namep - points to a file path name
  3536                              <1> 	;    u.cdir - i-number of users directory
  3537                              <1> 	;    u.cdev - device number on which user directory resides	
  3538                              <1> 	; OUTPUTS ->
  3539                              <1> 	;    r1 - i-number of file
  3540                              <1> 	;    cdev
  3541                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3542                              <1> 	;               occurs in the search for file path name.
  3543                              <1> 	;	        If no match u.dirb points to the end of 
  3544                              <1> 	;               the directory and r1 = i-number of the current
  3545                              <1> 	;	        directory.	
  3546                              <1> 	; ((AX = R1))
  3547                              <1> 	;
  3548                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3549                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3550                              <1> 	;
  3551                              <1> 
  3552 000049DC 66A1[606F0000]      <1> 	mov	ax, [u.cdir]
  3553                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3554                              <1> 			      ; / in r1
  3555 000049E2 668B15[A06F0000]    <1> 	mov	dx, [u.cdrv]
  3556 000049E9 668915[406F0000]    <1> 	mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3557                              <1> 				    ; device/drive number is in 1 byte, 
  3558                              <1> 				    ; not in 1 word!
  3559                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3560                              <1> 				; / into cdev
  3561                              <1> 	; 12/10/2015
  3562                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3563                              <1>       	 ; convert virtual (pathname) addr to physical address
  3564 000049F0 E869010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3565                              <1> 		; esi = physical address of [u.namep]
  3566                              <1> 		; ecx = byte count in the page
  3567 000049F5 803E2F              <1> 	cmp	byte [esi], '/'
  3568                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3569 000049F8 751D                <1> 	jne	short namei_1
  3570                              <1> 		; bne 1f
  3571 000049FA FF05[746F0000]      <1> 	inc	dword [u.namep]
  3572                              <1> 		; inc u.namep / go to next char
  3573                              <1> 	; 03/02/2022
  3574 00004A00 49                  <1> 	dec	ecx
  3575                              <1> 	;dec	cx ; remain byte count in the page
  3576 00004A01 7506                <1> 	jnz	short namei_0
  3577                              <1> 	; 12/10/2015
  3578 00004A03 E856010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3579                              <1> 		; esi = physical address (page start + offset)
  3580                              <1> 		; ecx = byte count in the page
  3581 00004A08 4E                  <1> 	dec	esi
  3582                              <1> namei_0:
  3583 00004A09 46                  <1> 	inc 	esi  ; go to next char
  3584 00004A0A 66A1[4C6F0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3585                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3586 00004A10 C605[406F0000]00    <1> 	mov	byte [cdev], 0
  3587                              <1> 		; clr cdev / clear device number
  3588                              <1> namei_1: ; 1:
  3589 00004A17 F606FF              <1> 	test	byte [esi], 0FFh
  3590                              <1> namei_10: ; 03/02/2022 (jump from namei_8)
  3591 00004A1A 74BF                <1> 	jz	short getf4
  3592                              <1> 	;jz	nig
  3593                              <1> 		; tstb *u.namep / is the character in file name a nul
  3594                              <1> 		; beq nig / yes, end of file name reached; 
  3595                              <1> 			; / branch to "nig"
  3596                              <1> namei_2: ; 1:
  3597                              <1> 	; 18/10/2015
  3598 00004A1C 8935[CC6F0000]      <1> 	mov 	[nbase], esi
  3599 00004A22 66890D[D06F0000]    <1> 	mov 	[ncount], cx
  3600                              <1> 	;
  3601                              <1> 	;mov	dx, 2
  3602 00004A29 B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3603 00004A2B E895080000          <1> 	call	access
  3604                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3605                              <1> 	; 'access' will not return here if user has not "r" permission !
  3606                              <1> 	; 03/02/2022
  3607 00004A30 F605[596C0000]40    <1> 	test	byte [i.flgs+1], 40h
  3608                              <1> 	;test 	word [i.flgs], 4000h
  3609                              <1> 		; bit $40000,i.flgs / directory i-node?
  3610 00004A37 746A                <1>         jz      short namei_err
  3611                              <1> 		; beq error3 / no, got an error
  3612                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3613 00004A39 31C0                <1> 	xor	eax, eax
  3614 00004A3B A3[786F0000]        <1> 	mov	[u.off], eax ; 0
  3615 00004A40 66A1[5C6C0000]      <1> 	mov	ax, [i.size]
  3616 00004A46 A3[706F0000]        <1> 	mov	[u.dirp], eax
  3617                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3618                              <1> 		; clr u.off / u.off is file offset used by user
  3619 00004A4B C705[6C6F0000]-     <1> 	mov	dword [u.fofp], u.off
  3619 00004A51 [786F0000]          <1>
  3620                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3621                              <1> 				  ; / the offset portion of fsp entry
  3622                              <1> namei_3: ; 2:
  3623 00004A55 C705[7C6F0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3623 00004A5B [8E6F0000]          <1>
  3624                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3625                              <1> 				    ; / copied from a directory
  3626 00004A5F C705[806F0000]0A00- <1> 	mov 	dword [u.count], 10 	
  3626 00004A67 0000                <1>
  3627                              <1>  		; mov $10.,u.count / u.count is byte count 
  3628                              <1> 				 ; / for reads and writes
  3629 00004A69 66A1[3C6F0000]      <1> 	mov 	ax, [ii]
  3630                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3631 00004A6F FE05[BD6F0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3632 00004A75 E84B090000          <1>     	call	readi
  3633                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3634                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3635 00004A7A 8B0D[846F0000]      <1> 	mov 	ecx, [u.nread]
  3636 00004A80 09C9                <1> 	or 	ecx, ecx
  3637                              <1> 		; tst u.nread
  3638 00004A82 741B                <1> 	jz	short nib
  3639                              <1> 		; ble nib / gives error return
  3640                              <1> 	;
  3641 00004A84 668B1D[8E6F0000]    <1> 	mov 	bx, [u.dirbuf]
  3642 00004A8B 6621DB              <1> 	and 	bx, bx       
  3643                              <1> 		; tst u.dirbuf /
  3644 00004A8E 7522                <1> 	jnz	short namei_4
  3645                              <1> 		; bne 3f / branch when active directory entry 
  3646                              <1> 		       ; / (i-node word in entry non zero)
  3647 00004A90 A1[786F0000]        <1> 	mov	eax, [u.off]
  3648 00004A95 83E80A              <1> 	sub	eax, 10
  3649 00004A98 A3[706F0000]        <1> 	mov	[u.dirp], eax
  3650                              <1> 		; mov u.off,u.dirp
  3651                              <1> 		; sub $10.,u.dirp
  3652 00004A9D EBB6                <1> 	jmp	short namei_3
  3653                              <1> 		; br 2b
  3654                              <1> 
  3655                              <1> 	; 18/07/2013
  3656                              <1> nib: 
  3657 00004A9F 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3658 00004AA1 F9                  <1> 	stc
  3659                              <1> nig:
  3660 00004AA2 C3                  <1> 	retn
  3661                              <1> 
  3662                              <1> namei_err:
  3663                              <1> 	; 16/06/2015
  3664 00004AA3 C705[AB6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3664 00004AAB 0000                <1>
  3665 00004AAD E929F0FFFF          <1> 	jmp	error
  3666                              <1> 
  3667                              <1> namei_4: ; 3:
  3668                              <1> 	; 18/10/2015
  3669                              <1> 	; 12/10/2015
  3670                              <1> 	; 21/08/2015
  3671                              <1> 	; 18/07/2015
  3672 00004AB2 8B2D[746F0000]      <1> 	mov	ebp, [u.namep]
  3673                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3674 00004AB8 BF[906F0000]        <1> 	mov 	edi, u.dirbuf + 2
  3675                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3676                              <1> 	; 18/10/2015
  3677 00004ABD 8B35[CC6F0000]      <1> 	mov	esi, [nbase]	
  3678 00004AC3 668B0D[D06F0000]    <1> 	mov	cx, [ncount]
  3679                              <1> 	;
  3680 00004ACA 6621C9              <1> 	and	cx, cx
  3681 00004ACD 7505                <1> 	jnz	short namei_5	
  3682                              <1> 	;
  3683 00004ACF E890000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3684                              <1> 		; esi = physical address (page start + offset)
  3685                              <1> 		; ecx = byte count in the page
  3686                              <1> namei_5: ; 3:
  3687 00004AD4 45                  <1> 	inc	ebp ; 18/07/2015
  3688 00004AD5 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3689                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3690 00004AD6 08C0                <1> 	or 	al, al
  3691 00004AD8 741C                <1> 	jz 	short namei_7
  3692                              <1> 		; beq 3f / if char is nul, then the last char in string
  3693                              <1> 			; / has been moved
  3694 00004ADA 3C2F                <1> 	cmp	al, '/'
  3695                              <1> 		; cmp r4,$'/ / is char a </>
  3696 00004ADC 7418                <1> 	je 	short namei_7
  3697                              <1> 		; beq 3f
  3698                              <1> 	; 03/02/2022
  3699 00004ADE 49                  <1> 	dec	ecx	
  3700                              <1> 	; 12/10/2015
  3701                              <1> 	;dec	cx ; remain byte count in the page
  3702 00004ADF 7505                <1> 	jnz	short namei_6
  3703 00004AE1 E87E000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3704                              <1> 		; esi = physical address (page start + offset)
  3705                              <1> 		; ecx = byte count in the page
  3706                              <1> namei_6:
  3707 00004AE6 81FF[986F0000]      <1>         cmp     edi, u.dirbuf + 10
  3708                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3709                              <1> 				     ; / all 8 bytes of file name
  3710 00004AEC 74E6                <1> 	je	short namei_5
  3711                              <1> 		; beq 3b
  3712 00004AEE AE                  <1> 	scasb	
  3713                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3714                              <1> 			      ; / char read from directory
  3715 00004AEF 74E3                <1> 	je 	short namei_5
  3716                              <1> 		; beq 3b / branch if chars match
  3717                              <1> namei_9:
  3718 00004AF1 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3719                              <1> 		; br 2b / file names do not match go to next directory entry
  3720                              <1> namei_7: ; 3:
  3721 00004AF6 81FF[986F0000]      <1> 	cmp	edi, u.dirbuf + 10
  3722                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3723 00004AFC 7406                <1> 	je	short namei_8
  3724                              <1> 		; beq 3f
  3725 00004AFE 8A27                <1> 	mov 	ah, [edi]
  3726                              <1> 	;inc 	edi 
  3727 00004B00 20E4                <1> 	and 	ah, ah
  3728                              <1> 		; tstb (r3)+ /
  3729                              <1>         ;jnz	namei_3
  3730                              <1> 		; bne 2b
  3731                              <1> 	; 03/02/2020
  3732 00004B02 75ED                <1> 	jnz	short namei_9
  3733                              <1> namei_8: ; 3
  3734 00004B04 892D[746F0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3735                              <1> 		; mov r2,u.namep / u.namep points to char 
  3736                              <1> 			       ; / following a / or nul
  3737                              <1> 	;mov	bx, [u.dirbuf]
  3738                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3739                              <1> 				; / entry to r1
  3740                              <1> 	;;;;
  3741                              <1> 	; 14/05/2022 - Retro UNIX (8086/386) feature only !
  3742                              <1> 	; ! 'pwd' utility modification !
  3743                              <1> 	; ((if directory entry name is a dotdot)))
  3744                              <1> 	;; check if it is mounted device's root directory inode
  3745                              <1> 	; and if so, replace it with parent dir inode number
  3746                              <1> 	;  of mounting directory in [mntp].
  3747                              <1> 
  3748 00004B0A 668B1D[8E6F0000]    <1> 	mov	bx, [u.dirbuf]
  3749                              <1> 
  3750 00004B11 6683FB29            <1> 	cmp	bx, 41 ; root directory inode number
  3751 00004B15 753C                <1> 	jne	short namei_11
  3752                              <1> 
  3753 00004B17 663B1D[3C6F0000]    <1> 	cmp	bx, [ii] ; for root dir, '.' & '..' is 41
  3754 00004B1E 7533                <1> 	jne	short namei_11 ; not root dir (of mounted dev)
  3755                              <1> 
  3756                              <1> 	;cmp	[idev], bh ; 0
  3757 00004B20 383D[406F0000]      <1> 	cmp	[cdev], bh ; 0
  3758                              <1> 			; 0 = root fs, dev num in [rdev]
  3759                              <1> 			; 1 = mounted, dev num in [mdev]
  3760 00004B26 762B                <1> 	jna	short namei_11
  3761                              <1> 
  3762                              <1> 	; dotdot (parent directory link) check
  3763 00004B28 66813D[906F0000]2E- <1> 	cmp	word [u.dirbuf+2], '..'
  3763 00004B30 2E                  <1>
  3764 00004B31 7520                <1> 	jne	short namei_11
  3765 00004B33 803D[926F0000]00    <1> 	cmp	byte [u.dirbuf+4], 0
  3766 00004B3A 7517                <1> 	jne	short namei_11
  3767                              <1> 	
  3768                              <1> 	; (This may not be necessary because [idev] = 1
  3769                              <1> 	; and [mnti] is expected as a sub dir inode number)
  3770 00004B3C 66391D[466F0000]    <1> 	cmp	[mnti], bx ; 41
  3771 00004B43 760E                <1> 	jna	short namei_11
  3772                              <1> 	
  3773                              <1> 	; change inumber to parent dir inum of mount directory
  3774 00004B45 668B1D[486F0000]    <1> 	mov	bx, [mntp]
  3775 00004B4C C605[406F0000]00    <1> 	mov	byte [cdev], 0 ; root fs
  3776                              <1> namei_11:
  3777                              <1> 	;;;;
  3778                              <1> 
  3779 00004B53 20C0                <1> 	and 	al, al
  3780                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3781                              <1> 		      ;  / if r4 = </> then go to next directory
  3782                              <1> 	; 15/05/2022
  3783 00004B55 6689D8              <1> 	mov	ax, bx
  3784                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  3785                              <1>   	; 03/02/2022
  3786 00004B58 E9BDFEFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3787                              <1> 	;jnz	namei_2 
  3788                              <1> 		; bne 1b
  3789                              <1> 	; AX = i-number of the file
  3790                              <1> ;;nig:
  3791 00004B5D C3                  <1> 	retn
  3792                              <1> 		; tst (r0)+ / gives non-error return
  3793                              <1> ;;nib:
  3794                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3795                              <1> 		       ; ax = 0 -> file not found 
  3796                              <1> ;;	stc	; 27/05/2013
  3797                              <1> ;;	retn
  3798                              <1> 		; rts r0
  3799                              <1> 
  3800                              <1> trans_addr_nmbp:
  3801                              <1> 	; 03/02/2022
  3802                              <1> 	; 18/10/2015
  3803                              <1> 	; 12/10/2015
  3804 00004B5E 8B2D[746F0000]      <1> 	mov 	ebp, [u.namep]
  3805                              <1> trans_addr_nm:
  3806                              <1> 	; 03/02/2022
  3807                              <1> 	; Convert virtual (pathname) address to physical address
  3808                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3809                              <1> 	; 18/10/2015
  3810                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3811                              <1> 	; 02/07/2015
  3812                              <1> 	; 17/06/2015
  3813                              <1> 	; 16/06/2015
  3814                              <1> 	;
  3815                              <1> 	; INPUTS: 
  3816                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3817                              <1> 	;	[u.pgdir] = user's page directory
  3818                              <1> 	; OUTPUT:
  3819                              <1> 	;       esi = physical address of the pathname
  3820                              <1> 	;	ecx = remain byte count in the page
  3821                              <1> 	;
  3822                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3823                              <1> 	;
  3824                              <1> 
  3825                              <1> 	; 03/02/2022
  3826 00004B64 29C9                <1> 	sub	ecx, ecx
  3827                              <1> 
  3828 00004B66 833D[B36F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3829 00004B6D 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3830                              <1> 				     ; it is already physical address
  3831 00004B6F 50                  <1>    	push	eax	
  3832 00004B70 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3833 00004B72 E849E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3834 00004B77 7204                <1> 	jc	short tr_addr_nm_err
  3835                              <1> 	; 18/10/2015
  3836                              <1> 	; eax = physical address 
  3837                              <1> 	; cx = remain byte count in page (1-4096) 
  3838                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3839 00004B79 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3840 00004B7B 58                  <1> 	pop	eax 
  3841 00004B7C C3                  <1> 	retn
  3842                              <1> 
  3843                              <1> tr_addr_nm_err:
  3844 00004B7D A3[AB6F0000]        <1> 	mov	[u.error], eax
  3845                              <1> 	;pop 	eax
  3846 00004B82 E954EFFFFF          <1> 	jmp	error
  3847                              <1> 
  3848                              <1> trans_addr_nmk:
  3849                              <1> 	; 12/10/2015
  3850                              <1> 	; 02/07/2015
  3851 00004B87 8B35[746F0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3852                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3853                              <1> 	; 03/02/2022
  3854 00004B8D B510                <1> 	mov	ch, PAGE_SIZE/256
  3855 00004B8F C3                  <1> 	retn
  3856                              <1> 
  3857                              <1> syschdir:
  3858                              <1> 	; 03/02/2022
  3859                              <1> 	; / makes the directory specified in the argument
  3860                              <1> 	; / the current directory
  3861                              <1> 	;
  3862                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3863                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3864                              <1> 	;
  3865                              <1> 	; 'syschdir' makes the directory specified in its argument
  3866                              <1> 	; the current working directory.
  3867                              <1> 	;
  3868                              <1> 	; Calling sequence:
  3869                              <1> 	;	syschdir; name
  3870                              <1> 	; Arguments:
  3871                              <1> 	;	name - address of the path name of a directory
  3872                              <1> 	;	       terminated by nul byte.	
  3873                              <1> 	; Inputs: -
  3874                              <1> 	; Outputs: -
  3875                              <1> 	; ...............................................................
  3876                              <1> 	;				
  3877                              <1> 	; Retro UNIX 8086 v1 modification:
  3878                              <1> 	;	 The user/application program puts address of 
  3879                              <1> 	;	 the path name in BX register as 'syschdir' 
  3880                              <1> 	; 	 system call argument.
  3881                              <1> 
  3882 00004B90 891D[746F0000]      <1> 	mov	[u.namep], ebx
  3883                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  3884 00004B96 E841FEFFFF          <1> 	call	namei
  3885                              <1> 		; jsr r0,namei / find its i-number
  3886                              <1> 	;jc	error
  3887                              <1> 		; br error3
  3888 00004B9B 730F                <1> 	jnc	short syschdir0
  3889                              <1> 	; 'directory not found !' error
  3890 00004B9D C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3890 00004BA5 0000                <1>
  3891 00004BA7 E92FEFFFFF          <1> 	jmp	error
  3892                              <1> syschdir0:
  3893                              <1> 	; 03/02/2022
  3894 00004BAC B202                <1> 	mov	dl, 2  ; read access ; 03/02/2022 (BugFix)
  3895 00004BAE E812070000          <1> 	call	access
  3896                              <1> 		; jsr r0,access; 2 / get i-node into core
  3897                              <1> 	; 03/02/2022
  3898 00004BB3 F605[596C0000]40    <1> 	test	byte [i.flgs+1], 40h
  3899                              <1> 	;test	word [i.flgs], 4000h
  3900                              <1> 		; bit $40000,i.flgs / is it a directory?
  3901                              <1> 	;jz	error 
  3902                              <1> 		; beq error3 / no error
  3903 00004BBA 750F                <1> 	jnz	short syschdir1
  3904 00004BBC C705[AB6F0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3904 00004BC4 0000                <1>
  3905 00004BC6 E910EFFFFF          <1> 	jmp	error
  3906                              <1> syschdir1:
  3907 00004BCB 66A3[606F0000]      <1> 	mov	[u.cdir], ax
  3908                              <1> 		; mov r1,u.cdir / move i-number to users 
  3909                              <1> 			      ; / current directory
  3910 00004BD1 66A1[406F0000]      <1> 	mov	ax, [cdev]
  3911 00004BD7 66A3[A06F0000]      <1> 	mov	[u.cdrv], ax
  3912                              <1> 		; mov cdev,u.cdev / move its device to users 
  3913                              <1> 			        ; / current device
  3914 00004BDD E919EFFFFF          <1> 	jmp	sysret
  3915                              <1> 		; br sysret3
  3916                              <1> 	
  3917                              <1> syschmod: ; < change mode of file >
  3918                              <1> 	; 29/04/2022 (bugfix)
  3919                              <1> 	; 03/02/2022
  3920                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3921                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3922                              <1> 	;
  3923                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3924                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3925                              <1> 	; changed to 'mode'.
  3926                              <1> 	;
  3927                              <1> 	; Calling sequence:
  3928                              <1> 	;	syschmod; name; mode
  3929                              <1> 	; Arguments:
  3930                              <1> 	;	name - address of the file name
  3931                              <1> 	;	       terminated by null byte.
  3932                              <1> 	;	mode - (new) mode/flags < attributes >
  3933                              <1> 	;	
  3934                              <1> 	; Inputs: -
  3935                              <1> 	; Outputs: -
  3936                              <1> 	; ...............................................................
  3937                              <1> 	;				
  3938                              <1> 	; Retro UNIX 8086 v1 modification: 
  3939                              <1> 	;       'syschmod' system call has two arguments; so,
  3940                              <1> 	;	* 1st argument, name is pointed to by BX register
  3941                              <1> 	;	* 2nd argument, mode is in CX register
  3942                              <1> 	;
  3943                              <1> 	; Mode bits (Flags):
  3944                              <1> 	;	bit 0 - write permission for non-owner (1)
  3945                              <1> 	;	bit 1 - read permission for non-owner (2)
  3946                              <1> 	;	bit 2 - write permission for owner (4)
  3947                              <1> 	;	bit 3 - read permission for owner (8)
  3948                              <1> 	;	bit 4 - executable flag (16) 	
  3949                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  3950                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3951                              <1> 	;	bit 12 - large file flag (4096)
  3952                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  3953                              <1> 	;	bit 14 - directory flag (16384)
  3954                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  3955                              <1> 
  3956                              <1> 	; / name; mode
  3957 00004BE2 E815000000          <1> 	call	isown
  3958                              <1> 		;jsr r0,isown / get the i-node and check user status
  3959                              <1> 	; 03/02/2022
  3960 00004BE7 F605[596C0000]40    <1> 	test	byte [i.flgs+1], 40h
  3961                              <1> 	;test	word [i.flgs], 4000h
  3962                              <1> 		; bit $40000,i.flgs / directory?
  3963 00004BEE 7402                <1> 	jz	short syschmod1
  3964                              <1> 		; beq 2f / no
  3965                              <1> 	; AL = (new) mode
  3966 00004BF0 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3967                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3968                              <1> 			   ; / executable modes
  3969                              <1> syschmod1: ; 2:
  3970 00004BF2 A2[586C0000]        <1> 	mov	[i.flgs], al	
  3971                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3972                              <1> 	;jmp	short isown1
  3973                              <1> 	;	; br 1f ; (jmp sysret4)
  3974                              <1> 	; 29/04/2022
  3975 00004BF7 E9FFEEFFFF          <1> 	jmp	sysret
  3976                              <1> 
  3977                              <1> isown:
  3978                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3979                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3980                              <1> 	;
  3981                              <1> 	; 'isown' is given a file name (the 1st argument).
  3982                              <1> 	;  It find the i-number of that file via 'namei' 
  3983                              <1> 	;  then gets the i-node into core via 'iget'.
  3984                              <1> 	;  It then tests to see if the user is super user. 
  3985                              <1> 	;  If not, it cheks to see if the user is owner of 
  3986                              <1> 	;  the file. If he is not an error occurs.
  3987                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3988                              <1> 	;  the inode has been modificed and the 2nd argument of
  3989                              <1> 	;  the call is put in r2.
  3990                              <1> 	;
  3991                              <1> 	; INPUTS ->
  3992                              <1> 	;    arguments of syschmod and syschown calls
  3993                              <1> 	; OUTPUTS ->
  3994                              <1> 	;    u.uid - id of user
  3995                              <1> 	;    imod - set to a 1
  3996                              <1> 	;    r2 - contains second argument of the system call				 	
  3997                              <1> 	;
  3998                              <1> 	;   ((AX=R2) output as 2nd argument)
  3999                              <1> 	;
  4000                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4001                              <1> 	;
  4002                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4003                              <1> 	;; ! 2nd argument on top of stack !
  4004                              <1> 	;; 22/06/2015 - 32 bit modifications
  4005                              <1> 	;; 07/07/2013
  4006 00004BFC 891D[746F0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4007 00004C02 51                  <1> 	push 	ecx ;; 2nd argument
  4008                              <1> 	;;
  4009 00004C03 E8D4FDFFFF          <1> 	call	namei
  4010                              <1> 		; jsr r0,namei / get its i-number
  4011                              <1>        ; Retro UNIX 8086 v1 modification !
  4012                              <1>        ; ax = 0 -> file not found 
  4013                              <1> 	;and	ax, ax
  4014                              <1> 	;jz	error
  4015                              <1> 	;jc	error ; 27/05/2013
  4016                              <1> 		; br error3
  4017 00004C08 730F                <1> 	jnc	short isown0
  4018                              <1> 	; 'file not found !' error
  4019 00004C0A C705[AB6F0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4019 00004C12 0000                <1>
  4020 00004C14 E9C2EEFFFF          <1> 	jmp	error
  4021                              <1> isown0:
  4022 00004C19 E8D3050000          <1> 	call	iget
  4023                              <1> 		; jsr r0,iget / get i-node into core
  4024 00004C1E A0[A26F0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4025 00004C23 08C0                <1> 	or	al, al
  4026                              <1> 		; tstb u.uid / super user?
  4027 00004C25 7417                <1> 	jz	short isown1
  4028                              <1> 		; beq 1f / yes, branch
  4029 00004C27 3A05[5B6C0000]      <1> 	cmp	al, [i.uid]
  4030                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4031                              <1> 				 ; / the file
  4032                              <1> 	;jne	error
  4033                              <1> 		; beq 1f / yes
  4034                              <1> 		; jmp error3 / no, error
  4035 00004C2D 740F                <1> 	je	short isown1
  4036                              <1> 
  4037 00004C2F C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4037 00004C37 0000                <1>
  4038                              <1> 			;  'permission denied !' error
  4039 00004C39 E99DEEFFFF          <1> 	jmp	error
  4040                              <1> isown1: ; 1:
  4041 00004C3E E8B8060000          <1> 	call	setimod
  4042                              <1> 		; jsr r0,setimod / indicates 
  4043                              <1> 		;	       ; / i-node has been modified
  4044 00004C43 58                  <1> 	pop	eax ; 2nd argument
  4045                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4046                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4047 00004C44 C3                  <1> 	retn
  4048                              <1> 		; rts r0
  4049                              <1> 
  4050                              <1> ;;arg:  ; < get system call arguments >
  4051                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4052                              <1> 	; of form:
  4053                              <1> 	;	sys 'routine' ; arg1
  4054                              <1> 	;		or
  4055                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4056                              <1> 	;		or
  4057                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4058                              <1> 	;	
  4059                              <1> 	; INPUTS ->
  4060                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4061                              <1> 	;	This pointers's value is actually the value of
  4062                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4063                              <1> 	;	made to process the sys instruction
  4064                              <1> 	;    r0 - contains the return address for the routine
  4065                              <1> 	;	that called arg. The data in the word pointer 
  4066                              <1> 	;	to by the return address is used as address
  4067                              <1> 	;	in which the extracted argument is stored   		
  4068                              <1> 	;    	
  4069                              <1> 	; OUTPUTS ->
  4070                              <1> 	;    'address' - contains the extracted argument 
  4071                              <1> 	;    u.sp+18 - is incremented by 2 
  4072                              <1> 	;    r1 - contains the extracted argument
  4073                              <1> 	;    r0 - points to the next instruction to be
  4074                              <1> 	;	 executed in the calling routine.
  4075                              <1> 	;
  4076                              <1>   
  4077                              <1> 	; mov u.sp,r1
  4078                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4079                              <1> 			; / into argument of arg2
  4080                              <1> 	; add $2,18.(r1) / point pc on stack 
  4081                              <1> 			      ; / to next system argument
  4082                              <1> 	; rts r0
  4083                              <1> 
  4084                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4085                              <1> 	; 'arg2' takes first argument in system call
  4086                              <1> 	;  (pointer to name of the file) and puts it in location
  4087                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4088                              <1> 	;  and on top of the stack
  4089                              <1> 	;	
  4090                              <1> 	; INPUTS ->
  4091                              <1> 	;    u.sp, r0
  4092                              <1> 	;    	
  4093                              <1> 	; OUTPUTS ->
  4094                              <1> 	;    u.namep
  4095                              <1> 	;    u.off 
  4096                              <1> 	;    u.off pushed on stack
  4097                              <1> 	;    r1
  4098                              <1> 	;
  4099                              <1> 
  4100                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4101                              <1> 				; / first arg in sys call
  4102                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4103                              <1> 				; / second arg in sys call
  4104                              <1> 	; mov r0,r1 / r0 points to calling routine
  4105                              <1> 	; mov (sp),r0 / put operation code back in r0
  4106                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4107                              <1> 			; / on stack
  4108                              <1> 	; jmp (r1) / return to calling routine
  4109                              <1> 
  4110                              <1> syschown: ; < change owner of file >
  4111                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4112                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4113                              <1> 	;
  4114                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4115                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4116                              <1> 	; changed to 'owner'
  4117                              <1> 	;
  4118                              <1> 	; Calling sequence:
  4119                              <1> 	;	syschown; name; owner
  4120                              <1> 	; Arguments:
  4121                              <1> 	;	name - address of the file name
  4122                              <1> 	;	       terminated by null byte.
  4123                              <1> 	;	owner - (new) owner (number/ID)
  4124                              <1> 	;	
  4125                              <1> 	; Inputs: -
  4126                              <1> 	; Outputs: -
  4127                              <1> 	; ...............................................................
  4128                              <1> 	;				
  4129                              <1> 	; Retro UNIX 8086 v1 modification: 
  4130                              <1> 	;       'syschown' system call has two arguments; so,
  4131                              <1> 	;	* 1st argument, name is pointed to by BX register
  4132                              <1> 	;	* 2nd argument, owner number is in CX register
  4133                              <1> 	;
  4134                              <1> 	; / name; owner
  4135 00004C45 E8B2FFFFFF          <1> 	call	isown
  4136                              <1> 		; jsr r0,isown / get the i-node and check user status
  4137 00004C4A 803D[A26F0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4138                              <1> 		; tstb u.uid / super user
  4139 00004C51 7418                <1> 	jz	short syschown1
  4140                              <1> 		; beq 2f / yes, 2f
  4141 00004C53 F605[586C0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4142                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4143                              <1> 	;jnz	error
  4144                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4145 00004C5A 740F                <1> 	jz	short syschown1
  4146                              <1> 	; 'permission denied !'
  4147 00004C5C C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4147 00004C64 0000                <1>
  4148 00004C66 E970EEFFFF          <1> 	jmp	error
  4149                              <1> syschown1: ; 2:
  4150                              <1> 	; AL = owner (number/ID)
  4151 00004C6B A2[5B6C0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4152                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4153                              <1> 			       ; / in the i-node
  4154 00004C70 E986EEFFFF          <1> 	jmp	sysret
  4155                              <1> 	; 1: 
  4156                              <1> 		; jmp sysret4
  4157                              <1> 	; 3:
  4158                              <1> 		; jmp	error
  4159                              <1> 
  4160                              <1> systime: ; / get time of year
  4161                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4162                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4163                              <1> 	;
  4164                              <1> 	; 20/06/2013
  4165                              <1> 	; 'systime' gets the time of the year.
  4166                              <1> 	; The present time is put on the stack.
  4167                              <1> 	;
  4168                              <1> 	; Calling sequence:
  4169                              <1> 	;	systime
  4170                              <1> 	; Arguments: -
  4171                              <1> 	;	
  4172                              <1> 	; Inputs: -
  4173                              <1> 	; Outputs: sp+2, sp+4 - present time
  4174                              <1> 	; ...............................................................
  4175                              <1> 	;	
  4176                              <1> 	; Retro UNIX 8086 v1 modification: 
  4177                              <1> 	;       'systime' system call will return to the user
  4178                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4179                              <1> 	;
  4180                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4181                              <1> 	;	system call for PC compatibility !!		 	
  4182                              <1> 
  4183 00004C75 E8AFE9FFFF          <1> 	call 	epoch
  4184 00004C7A A3[5C6F0000]        <1> 	mov 	[u.r0], eax
  4185                              <1> 		; mov s.time,4(sp)
  4186                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4187                              <1> 				   ; / on the stack
  4188                              <1> 		; br sysret4
  4189 00004C7F E977EEFFFF          <1> 	jmp	sysret 
  4190                              <1> 
  4191                              <1> sysstime: ; / set time
  4192                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4193                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4194                              <1> 	;
  4195                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4196                              <1> 	;
  4197                              <1> 	; Calling sequence:
  4198                              <1> 	;	sysstime
  4199                              <1> 	; Arguments: -
  4200                              <1> 	;	
  4201                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4202                              <1> 	; Outputs: -
  4203                              <1> 	; ...............................................................
  4204                              <1> 	;	
  4205                              <1> 	; Retro UNIX 8086 v1 modification: 
  4206                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4207                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4208                              <1> 	; 
  4209                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4210                              <1> 	;	to get sysstime system call arguments from the user;
  4211                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4212                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4213                              <1> 	;
  4214                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4215                              <1> 	;	system call for PC compatibility !!	
  4216                              <1> 
  4217 00004C84 803D[A26F0000]00    <1> 	cmp	byte [u.uid], 0
  4218                              <1> 		; tstb u.uid / is user the super user
  4219                              <1> 	;ja	error
  4220                              <1> 		; bne error4 / no, error
  4221 00004C8B 760F                <1> 	jna	short systime1
  4222                              <1> 	; 'permission denied !'
  4223 00004C8D C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4223 00004C95 0000                <1>
  4224 00004C97 E93FEEFFFF          <1> 	jmp	error
  4225                              <1> systime1:
  4226                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4227                              <1> 	; EBX = unix (epoch) time (from user)
  4228 00004C9C 89D8                <1> 	mov	eax, ebx
  4229 00004C9E E806EBFFFF          <1> 	call 	set_date_time
  4230                              <1> 		; mov 4(sp),s.time
  4231                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4232 00004CA3 E953EEFFFF          <1> 	jmp	sysret
  4233                              <1> 		; br sysret4
  4234                              <1> 
  4235                              <1> sysbreak:
  4236                              <1> 	; 18/10/2015
  4237                              <1> 	; 07/10/2015
  4238                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4239                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4240                              <1> 	;
  4241                              <1> 	; 'sysbreak' sets the programs break points. 
  4242                              <1> 	; It checks the current break point (u.break) to see if it is
  4243                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4244                              <1> 	; even address (if it was odd) and the area between u.break
  4245                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4246                              <1> 	; in u.break and control is passed to 'sysret'.
  4247                              <1> 	;
  4248                              <1> 	; Calling sequence:
  4249                              <1> 	;	sysbreak; addr
  4250                              <1> 	; Arguments: -
  4251                              <1> 	;	
  4252                              <1> 	; Inputs: u.break - current breakpoint
  4253                              <1> 	; Outputs: u.break - new breakpoint 
  4254                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4255                              <1> 	; ...............................................................
  4256                              <1> 	;	
  4257                              <1> 	; Retro UNIX 8086 v1 modification:
  4258                              <1> 	;	The user/application program puts breakpoint address
  4259                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4260                              <1> 	; 	(argument transfer method 1)
  4261                              <1> 	;
  4262                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4263                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4264                              <1> 	;  NOTE:
  4265                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4266                              <1> 	;	'u.break' address) of user's memory for original unix's
  4267                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4268                              <1> 
  4269                              <1> 		; mov u.break,r1 / move users break point to r1
  4270                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4271                              <1> 		; blos 1f / yes, 1f
  4272                              <1> 	; 23/06/2015
  4273 00004CA8 8B2D[886F0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4274                              <1> 	;and	ebp, ebp
  4275                              <1> 	;jz	short sysbreak_3 
  4276                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4277                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4278 00004CAE 8B15[546F0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4279 00004CB4 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4280                              <1> 	; 07/10/2015
  4281 00004CB7 891D[886F0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4282                              <1> 	;
  4283 00004CBD 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4284                              <1> 			   ; with top of user's stack (virtual!)
  4285 00004CBF 7327                <1> 	jnb	short sysbreak_3
  4286                              <1> 		; cmp r1,sp / is it the same or higher 
  4287                              <1> 			  ; / than the stack?
  4288                              <1> 		; bhis 1f / yes, 1f
  4289 00004CC1 89DE                <1> 	mov	esi, ebx
  4290 00004CC3 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4291 00004CC5 7621                <1> 	jna	short sysbreak_3 
  4292                              <1> 	;push	ebx
  4293                              <1> sysbreak_1:
  4294 00004CC7 89EB                <1> 	mov	ebx, ebp  
  4295 00004CC9 E8F2E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4296 00004CCE 0F82A9FEFFFF        <1> 	jc	tr_addr_nm_err
  4297                              <1> 	; 18/10/2015
  4298 00004CD4 89C7                <1> 	mov	edi, eax 
  4299 00004CD6 29C0                <1> 	sub	eax, eax ; 0
  4300                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4301 00004CD8 39CE                <1> 	cmp	esi, ecx
  4302 00004CDA 7302                <1> 	jnb	short sysbreak_2
  4303 00004CDC 89F1                <1> 	mov	ecx, esi
  4304                              <1> sysbreak_2:
  4305 00004CDE 29CE                <1> 	sub	esi, ecx
  4306 00004CE0 01CD                <1> 	add	ebp, ecx
  4307 00004CE2 F3AA                <1> 	rep 	stosb
  4308 00004CE4 09F6                <1> 	or	esi, esi
  4309 00004CE6 75DF                <1> 	jnz	short sysbreak_1
  4310                              <1> 	;
  4311                              <1> 		; bit $1,r1 / is it an odd address
  4312                              <1> 		; beq 2f / no, its even
  4313                              <1> 		; clrb (r1)+ / yes, make it even
  4314                              <1> 	; 2: / clear area between the break point and the stack
  4315                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4316                              <1> 		; bhis 1f / yes, quit
  4317                              <1> 		; clr (r1)+ / clear word
  4318                              <1> 		; br 2b / go back
  4319                              <1> 	;pop	ebx
  4320                              <1> sysbreak_3: ; 1:
  4321                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4322                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4323                              <1> 			; / in u.break (set new break point)
  4324                              <1> 		; br sysret4 / br sysret
  4325 00004CE8 E90EEEFFFF          <1> 	jmp	sysret
  4326                              <1> 
  4327                              <1> maknod: 
  4328                              <1> 	; 12/02/2022
  4329                              <1> 	; 03/02/2022
  4330                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4331                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4332                              <1> 	;
  4333                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4334                              <1> 	; for this i-node in the current directory.
  4335                              <1> 	;
  4336                              <1> 	; INPUTS ->
  4337                              <1> 	;    r1 - contains mode
  4338                              <1> 	;    ii - current directory's i-number	
  4339                              <1> 	;    	
  4340                              <1> 	; OUTPUTS ->
  4341                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4342                              <1> 	;    i.flgs - flags in new i-node 
  4343                              <1> 	;    i.uid - filled with u.uid
  4344                              <1> 	;    i.nlks - 1 is put in the number of links
  4345                              <1> 	;    i.ctim - creation time				
  4346                              <1> 	;    i.ctim+2 - modification time
  4347                              <1> 	;    imod - set via call to setimod
  4348                              <1> 	;	
  4349                              <1> 	; ((AX = R1)) input
  4350                              <1> 	;
  4351                              <1> 	; (Retro UNIX Prototype : 
  4352                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4353                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4354                              <1> 
  4355                              <1> 	; / r1 contains the mode
  4356 00004CED 80CC80              <1> 	or 	ah, 80h ; 10000000b
  4357                              <1> 		; bis $100000,r1 / allocate flag set
  4358 00004CF0 6650                <1> 	push	ax ; *
  4359                              <1> 		; mov r1,-(sp) / put mode on stack
  4360                              <1> 	; 31/07/2013
  4361 00004CF2 66A1[3C6F0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4362                              <1> 		; mov ii,r1 / move current i-number to r1
  4363 00004CF8 B201                <1> 	mov	dl, 1 ; owner flag mask
  4364 00004CFA E8C6050000          <1> 	call	access	
  4365                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4366                              <1> 	; 03/02/2022
  4367 00004CFF 50                  <1> 	push	eax ; **
  4368                              <1> 	;push	ax
  4369                              <1> 		; mov r1,-(sp) / put i-number on stack
  4370 00004D00 66B82800            <1> 	mov	ax, 40
  4371                              <1> 		; mov $40.,r1 / r1 = 40
  4372                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4373 00004D04 6640                <1> 	inc	ax
  4374                              <1> 		; inc r1 / r1 = r1 + 1
  4375 00004D06 E87F060000          <1> 	call	imap
  4376                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4377                              <1> 			    ; /	inode map in r2 & m
  4378                              <1>   
  4379                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4380                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4381                              <1> 
  4382                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4383                              <1> 	;	       Inode count must be checked here
  4384                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4385                              <1> 
  4386                              <1> 	; 12/02/2022 - Retro UNIX 386 v1.0 (Kernel v0.2.0.18)
  4387                              <1> 	; (inode count check)
  4388                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4389                              <1> 
  4390 00004D0B 730F                <1> 	jnc	short maknod2
  4391                              <1> 
  4392                              <1> 	; no free inode in inode table !
  4393 00004D0D C705[AB6F0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4393 00004D15 0000                <1>
  4394                              <1> 			; miscellaneous/other errors
  4395 00004D17 E9BFEDFFFF          <1> 	jmp	error	
  4396                              <1> maknod2: 	
  4397 00004D1C 8413                <1> 	test	[ebx], dl
  4398                              <1> 		; bitb mq,(r2) / is the i-node active
  4399 00004D1E 75E4                <1> 	jnz	short maknod1
  4400                              <1> 		; bne 1b / yes, try the next one
  4401 00004D20 0813                <1> 	or	[ebx], dl
  4402                              <1> 		; bisb mq,(r2) / no, make it active 
  4403                              <1> 			     ; / (put a 1 in the bit map)
  4404 00004D22 E8CA040000          <1> 	call	iget
  4405                              <1> 		; jsr r0,iget / get i-node into core
  4406                              <1> 	; 03/02/2022
  4407 00004D27 F605[596C0000]80    <1> 	test	byte [i.flgs+1], 80h
  4408                              <1> 	;test	word [i.flgs], 8000h 
  4409                              <1> 		; tst i.flgs / is i-node already allocated
  4410 00004D2E 75D4                <1> 	jnz	short maknod1	
  4411                              <1> 		; blt 1b / yes, look for another one
  4412 00004D30 66A3[8E6F0000]      <1> 	mov	[u.dirbuf], ax
  4413                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4414                              <1> 	; 03/02/2022
  4415 00004D36 58                  <1> 	pop	eax ; **
  4416                              <1> 	;pop	ax
  4417                              <1> 		; mov (sp)+,r1 / get current i-number back
  4418 00004D37 E8B5040000          <1> 	call	iget
  4419                              <1> 		; jsr r0,iget / get i-node in core
  4420 00004D3C E852F7FFFF          <1> 	call	mkdir
  4421                              <1> 		; jsr r0,mkdir / make a directory entry 
  4422                              <1> 			     ; / in current directory
  4423 00004D41 66A1[8E6F0000]      <1> 	mov	ax, [u.dirbuf]
  4424                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4425 00004D47 E8A5040000          <1> 	call	iget
  4426                              <1> 		; jsr r0,iget / get it into core
  4427                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4428                              <1> 	;mov	ecx, 8
  4429                              <1> 	; 03/02/2022 
  4430 00004D4C 29C9                <1> 	sub	ecx, ecx
  4431 00004D4E B108                <1> 	mov	cl, 8
  4432 00004D50 31C0                <1> 	xor	eax, eax ; 0
  4433 00004D52 BF[586C0000]        <1> 	mov	edi, inode 
  4434 00004D57 F3AB                <1> 	rep	stosd
  4435                              <1> 	;
  4436 00004D59 668F05[586C0000]    <1> 	pop	word [i.flgs] ; *
  4437                              <1> 		; mov (sp)+,i.flgs / fill flags
  4438 00004D60 8A0D[A26F0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4439 00004D66 880D[5B6C0000]      <1> 	mov 	[i.uid], cl
  4440                              <1> 		; movb u.uid,i.uid / user id	
  4441 00004D6C C605[5A6C0000]01    <1> 	mov     byte [i.nlks], 1
  4442                              <1> 		; movb $1,i.nlks / 1 link
  4443                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4444                              <1> 	;mov	eax, [s.time]
  4445                              <1> 	;mov 	[i.ctim], eax
  4446                              <1> 	 	; mov s.time,i.ctim / time created
  4447                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4448                              <1> 	; Retro UNIX 8086 v1 modification !
  4449                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4450                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4451                              <1> 	;call setimod
  4452                              <1> 		; jsr r0,setimod / set modified flag
  4453                              <1> 	;retn
  4454                              <1> 		; rts r0 / return
  4455                              <1> 	; 03/02/2022
  4456 00004D73 E983050000          <1> 	jmp	setimod
  4457                              <1> 
  4458                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4459                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4460                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4461                              <1> 	;
  4462                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4463                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4464                              <1> 	; The file descriptor refers to a file open for reading or
  4465                              <1> 	; writing. The read (or write) pointer is set as follows:
  4466                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4467                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4468                              <1> 	;	  current location plus offset.
  4469                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4470                              <1> 	;	  size of file plus offset.
  4471                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4472                              <1> 	;
  4473                              <1> 	; Calling sequence:
  4474                              <1> 	;	sysseek; offset; ptrname
  4475                              <1> 	; Arguments:
  4476                              <1> 	;	offset - number of bytes desired to move 
  4477                              <1> 	;		 the r/w pointer
  4478                              <1> 	;	ptrname - a switch indicated above
  4479                              <1> 	;
  4480                              <1> 	; Inputs: r0 - file descriptor 
  4481                              <1> 	; Outputs: -
  4482                              <1> 	; ...............................................................
  4483                              <1> 	;	
  4484                              <1> 	; Retro UNIX 8086 v1 modification: 
  4485                              <1> 	;       'sysseek' system call has three arguments; so,
  4486                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4487                              <1> 	;	* 2nd argument, offset is in CX register
  4488                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4489                              <1> 	;	
  4490                              <1> 
  4491 00004D78 E822000000          <1> 	call	seektell
  4492                              <1> 	; AX = u.count
  4493                              <1> 	; BX = *u.fofp
  4494                              <1> 		; jsr r0,seektell / get proper value in u.count
  4495                              <1> 		; add u.base,u.count / add u.base to it
  4496 00004D7D 0305[7C6F0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4497 00004D83 8903                <1> 	mov	[ebx], eax
  4498                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4499 00004D85 E971EDFFFF          <1> 	jmp	sysret
  4500                              <1> 		; br sysret4
  4501                              <1> 
  4502                              <1> systell: ; / get the r/w pointer
  4503                              <1> 	; 03/02/2022
  4504                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4505                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4506                              <1> 	;
  4507                              <1> 	; Retro UNIX 8086 v1 modification:
  4508                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4509                              <1> 	; 	    it returns with error !
  4510                              <1> 	; Inputs: r0 - file descriptor 
  4511                              <1> 	; Outputs: r0 - file r/w pointer
  4512                              <1> 
  4513                              <1> 	;xor	ecx, ecx ; 0
  4514                              <1> 	;mov	edx, 1 ; 05/08/2013
  4515                              <1> 	; 03/02/2022
  4516 00004D8A 29D2                <1> 	sub	edx, edx
  4517 00004D8C FEC2                <1> 	inc	dl
  4518                              <1> 	; edx = 1
  4519                              <1> 	;call 	seektell
  4520 00004D8E E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4521                              <1> 	;mov	ebx, [u.fofp]
  4522 00004D93 8B03                <1> 	mov	eax, [ebx]
  4523 00004D95 A3[5C6F0000]        <1> 	mov	[u.r0], eax
  4524 00004D9A E95CEDFFFF          <1> 	jmp	sysret
  4525                              <1> 
  4526                              <1> ; Original unix v1 'systell' system call:
  4527                              <1> 		; jsr r0,seektell
  4528                              <1> 		; br error4
  4529                              <1> 
  4530                              <1> seektell:
  4531                              <1> 	; 03/02/2022
  4532                              <1> 	; 03/01/2016
  4533                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4534                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4535                              <1> 	;
  4536                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4537                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4538                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4539                              <1> 	; getf. The i-node is brought into core and then u.count
  4540                              <1> 	; is checked to see it is a 0, 1, or 2.
  4541                              <1> 	; If it is 0 - u.count stays the same
  4542                              <1> 	;          1 - u.count = offset (u.fofp)
  4543                              <1> 	;	   2 - u.count = i.size (size of file)
  4544                              <1> 	; 	 		
  4545                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4546                              <1> 	;	Argument 1, file descriptor is in BX;
  4547                              <1> 	;	Argument 2, offset is in CX;
  4548                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4549                              <1> 	;
  4550                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4551                              <1> 	; call 	arg
  4552                              <1> 	;
  4553                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4554                              <1> 	;
  4555 00004D9F 890D[7C6F0000]      <1> 	mov 	[u.base], ecx ; offset
  4556                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4557                              <1> seektell0:
  4558 00004DA5 8915[806F0000]      <1> 	mov 	[u.count], edx
  4559                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4560                              <1> 	; mov	ax, bx
  4561                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4562                              <1> 			     ; / (index in u.fp list)
  4563                              <1> 	; call	getf
  4564                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4565                              <1> 	; BX = file descriptor (file number)
  4566 00004DAB E8F9FBFFFF          <1> 	call	getf1
  4567                              <1> 	; 03/02/2022
  4568 00004DB0 09C0                <1> 	or	eax, eax
  4569                              <1> 	;or	ax, ax ; i-number of the file
  4570                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4571                              <1> 		             ; / put it on the stack
  4572                              <1> 	;jz	error
  4573                              <1> 		; beq error4 / if i-number is 0, not active so error
  4574 00004DB2 750F                <1> 	jnz	short seektell1
  4575 00004DB4 C705[AB6F0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4575 00004DBC 0000                <1>
  4576 00004DBE E918EDFFFF          <1> 	jmp	error
  4577                              <1> seektell1:
  4578                              <1> 	;push	eax
  4579 00004DC3 80FC80              <1> 	cmp	ah, 80h
  4580 00004DC6 7203                <1> 	jb	short seektell2
  4581                              <1> 		; bgt .+4 / if its positive jump
  4582 00004DC8 66F7D8              <1> 	neg	ax
  4583                              <1> 		; neg r1 / if not make it positive
  4584                              <1> seektell2:
  4585 00004DCB E821040000          <1> 	call	iget
  4586                              <1> 		; jsr r0,iget / get its i-node into core
  4587 00004DD0 8B1D[6C6F0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4588 00004DD6 803D[806F0000]01    <1> 	cmp	byte [u.count], 1
  4589                              <1> 		; cmp u.count,$1 / is ptr name =1
  4590 00004DDD 7705                <1> 	ja	short seektell3
  4591                              <1> 		; blt 2f / no its zero
  4592 00004DDF 740A                <1> 	je	short seektell_4
  4593                              <1> 		; beq 1f / yes its 1
  4594 00004DE1 31C0                <1> 	xor	eax, eax
  4595                              <1> 	;jmp	short seektell_5
  4596 00004DE3 C3                  <1> 	retn
  4597                              <1> seektell3:
  4598                              <1> 	; 03/01/2016
  4599                              <1> 	;movzx  eax, word [i.size]
  4600 00004DE4 66A1[5C6C0000]      <1> 	mov	ax, [i.size]
  4601                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4602                              <1>                                    ; / in file in u.count
  4603                              <1> 	;jmp	short seektell_5
  4604                              <1> 		; br 2f
  4605 00004DEA C3                  <1> 	retn
  4606                              <1> seektell_4: ; 1: / ptrname =1
  4607                              <1> 	;mov	ebx, [u.fofp]
  4608 00004DEB 8B03                <1> 	mov	eax, [ebx]
  4609                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4610                              <1> ;seektell_5: ; 2: / ptrname =0
  4611                              <1> 	;mov	[u.count], eax
  4612                              <1> 	;pop	eax 
  4613                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4614 00004DED C3                  <1> 	retn
  4615                              <1> 		; rts r0
  4616                              <1> 
  4617                              <1> sysintr: ; / set interrupt handling
  4618                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4619                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4620                              <1> 	;
  4621                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4622                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4623                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4624                              <1> 	; If one does the interrupt character in the tty buffer is
  4625                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4626                              <1> 	; 'sysret' is just called.	
  4627                              <1> 	;
  4628                              <1> 	; Calling sequence:
  4629                              <1> 	;	sysintr; arg
  4630                              <1> 	; Argument:
  4631                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4632                              <1> 	;	    - if 1, intterupts cause their normal result
  4633                              <1> 	;		 i.e force an exit.
  4634                              <1> 	;	    - if arg is a location within the program,
  4635                              <1> 	;		control is passed to that location when
  4636                              <1> 	;		an interrupt occurs.	
  4637                              <1> 	; Inputs: -
  4638                              <1> 	; Outputs: -
  4639                              <1> 	; ...............................................................
  4640                              <1> 	;	
  4641                              <1> 	; Retro UNIX 8086 v1 modification: 
  4642                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4643                              <1> 	;	then branches into sysquit.
  4644                              <1> 	;
  4645 00004DEE 66891D[9A6F0000]    <1> 	mov	[u.intr], bx
  4646                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4647                              <1> 		; br 1f / go into quit routine
  4648 00004DF5 E901EDFFFF          <1> 	jmp	sysret
  4649                              <1> 
  4650                              <1> sysquit:
  4651                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4652                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4653                              <1> 	;
  4654                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4655                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4656                              <1> 	; tty exists. If one does the interrupt character in the tty
  4657                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4658                              <1> 	; 'sysret' is just called.	
  4659                              <1> 	;
  4660                              <1> 	; Calling sequence:
  4661                              <1> 	;	sysquit; arg
  4662                              <1> 	; Argument:
  4663                              <1> 	;	arg - if 0, this call diables quit signals from the
  4664                              <1> 	;		typewriter (ASCII FS)
  4665                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4666                              <1> 	;		cease and a core image to be produced.
  4667                              <1> 	;		 i.e force an exit.
  4668                              <1> 	;	    - if arg is an addres in the program,
  4669                              <1> 	;		a quit causes control to sent to that
  4670                              <1> 	;		location.	
  4671                              <1> 	; Inputs: -
  4672                              <1> 	; Outputs: -
  4673                              <1> 	; ...............................................................
  4674                              <1> 	;	
  4675                              <1> 	; Retro UNIX 8086 v1 modification: 
  4676                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4677                              <1> 	;	then branches into 'sysret'.
  4678                              <1> 	;
  4679 00004DFA 66891D[9C6F0000]    <1> 	mov	[u.quit], bx
  4680 00004E01 E9F5ECFFFF          <1> 	jmp	sysret
  4681                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4682                              <1> 	;1:
  4683                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4684                              <1> 			      ; / to r1
  4685                              <1> 		; beq sysret4 / return to user
  4686                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4687                              <1> 			   ; / in the tty buffer
  4688                              <1> 		; br sysret4 / return to user
  4689                              <1> 
  4690                              <1> syssetuid: ; / set process id
  4691                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4692                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4693                              <1> 	;
  4694                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4695                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4696                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4697                              <1> 	; Only the super user can make this call.	
  4698                              <1> 	;
  4699                              <1> 	; Calling sequence:
  4700                              <1> 	;	syssetuid
  4701                              <1> 	; Arguments: -
  4702                              <1> 	;
  4703                              <1> 	; Inputs: (u.r0) - contains the process id.
  4704                              <1> 	; Outputs: -
  4705                              <1> 	; ...............................................................
  4706                              <1> 	;	
  4707                              <1> 	; Retro UNIX 8086 v1 modification: 
  4708                              <1> 	;       BL contains the (new) user ID of the current process
  4709                              <1> 
  4710                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4711 00004E06 3A1D[A36F0000]      <1> 	cmp	bl, [u.ruid] 
  4712                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4713                              <1> 			       ; / id number
  4714 00004E0C 741E                <1> 	je	short setuid1
  4715                              <1> 		; beq 1f / yes
  4716 00004E0E 803D[A26F0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4717                              <1> 		; tstb u.uid / no, is current user the super user?
  4718                              <1> 	;ja	error
  4719                              <1> 		; bne error4 / no, error
  4720 00004E15 760F                <1> 	jna	short setuid0
  4721 00004E17 C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4721 00004E1F 0000                <1>
  4722                              <1> 				; 'permission denied !' error
  4723 00004E21 E9B5ECFFFF          <1> 	jmp	error
  4724                              <1> setuid0:
  4725 00004E26 881D[A36F0000]      <1> 	mov	[u.ruid], bl
  4726                              <1> setuid1: ; 1:
  4727 00004E2C 881D[A26F0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4728                              <1> 		; movb r1,u.uid / put process id in u.uid
  4729                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4730 00004E32 E9C4ECFFFF          <1> 	jmp	sysret
  4731                              <1> 		; br sysret4 / system return
  4732                              <1> 
  4733                              <1> sysgetuid: ; < get user id >
  4734                              <1> 	; 03/02/2022
  4735                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4736                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4737                              <1> 	;
  4738                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4739                              <1> 	; The real user ID identifies the person who is logged in,
  4740                              <1> 	; in contradistinction to the effective user ID, which
  4741                              <1> 	; determines his access permission at each moment. It is thus
  4742                              <1> 	; useful to programs which operate using the 'set user ID'
  4743                              <1> 	; mode, to find out who invoked them.	
  4744                              <1> 	;
  4745                              <1> 	; Calling sequence:
  4746                              <1> 	;	syssetuid
  4747                              <1> 	; Arguments: -
  4748                              <1> 	;
  4749                              <1> 	; Inputs: -
  4750                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4751                              <1> 	; ...............................................................
  4752                              <1> 	;	
  4753                              <1> 	; Retro UNIX 8086 v1 modification: 
  4754                              <1> 	;       AL contains the real user ID at return.
  4755                              <1> 	;
  4756                              <1> 	;movzx 	eax, byte [u.ruid]
  4757                              <1> 	; 03/03/2022
  4758 00004E37 A0[A36F0000]        <1> 	mov	al, [u.ruid]
  4759 00004E3C A3[5C6F0000]        <1> 	mov	[u.r0], eax
  4760                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4761 00004E41 E9B5ECFFFF          <1> 	jmp	sysret
  4762                              <1> 		; br sysret4 / systerm return, sysret
  4763                              <1> 
  4764                              <1> anyi: 
  4765                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4766                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4767                              <1> 	;
  4768                              <1> 	; 'anyi' is called if a file deleted while open.
  4769                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4770                              <1> 	;
  4771                              <1> 	; INPUTS ->
  4772                              <1> 	;    r1 - contains an i-number
  4773                              <1> 	;    fsp - start of table containing open files
  4774                              <1> 	;
  4775                              <1> 	; OUTPUTS ->
  4776                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4777                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4778                              <1> 	;    if file not found - bit in i-node map is cleared
  4779                              <1> 	;    			 (i-node is freed)
  4780                              <1> 	;               all blocks related to i-node are freed
  4781                              <1> 	;	        all flags in i-node are cleared
  4782                              <1> 	; ((AX = R1)) input
  4783                              <1> 	;
  4784                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4785                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4786                              <1> 	;
  4787                              <1> 		; / r1 contains an i-number
  4788 00004E46 BB[286D0000]        <1> 	mov	ebx, fsp
  4789                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4790                              <1> anyi_1: ; 1:
  4791 00004E4B 663B03              <1> 	cmp	ax, [ebx]
  4792                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4793 00004E4E 7433                <1> 	je	short anyi_3
  4794                              <1> 		; beq 1f / yes, 1f
  4795 00004E50 66F7D8              <1> 	neg	ax
  4796                              <1> 		; neg r1 / no complement r1
  4797 00004E53 663B03              <1> 	cmp	ax, [ebx]
  4798                              <1> 		; cmp r1,(r2) / do they match now?
  4799 00004E56 742B                <1> 	je	short anyi_3
  4800                              <1> 		; beq 1f / yes, transfer
  4801                              <1> 		; / i-numbers do not match
  4802 00004E58 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4803                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4804                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4805 00004E5B 81FB[1C6F0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4806                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4807                              <1> 				; / are we at last entry in the table
  4808 00004E61 72E8                <1> 	jb	short anyi_1
  4809                              <1> 		; blt 1b / no, check next entries i-number
  4810                              <1> 	;cmp	ax, 32768
  4811 00004E63 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4812                              <1> 		; tst r1 / yes, no match
  4813                              <1> 		; bge .+4
  4814 00004E66 7203                <1> 	jb	short anyi_2
  4815 00004E68 66F7D8              <1> 	neg	ax
  4816                              <1> 		; neg r1 / make i-number positive
  4817                              <1> anyi_2:	
  4818 00004E6B E81A050000          <1> 	call	imap
  4819                              <1> 		; jsr r0,imap / get address of allocation bit 
  4820                              <1> 			    ; / in the i-map in r2
  4821                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4822                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4823                              <1>  	; not	dx
  4824 00004E70 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4825                              <1>         ;and	[ebx], dx
  4826 00004E72 2013                <1> 	and 	[ebx], dl 
  4827                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4828 00004E74 E8A4040000          <1> 	call	itrunc
  4829                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4830 00004E79 66C705[586C0000]00- <1>  	mov 	word [i.flgs], 0
  4830 00004E81 00                  <1>
  4831                              <1> 		; clr i.flgs / clear all flags in the i-node
  4832 00004E82 C3                  <1> 	retn
  4833                              <1> 		;rts	r0 / return
  4834                              <1> anyi_3: ; 1: / i-numbers match
  4835 00004E83 FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4836                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4837                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4838 00004E86 C3                  <1> 	retn
  4839                              <1> 		; rts r0
  2049                                  %include 'u3.s'        ; 10/05/2015
  2050                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2051                              <1> ; Last Modification: 03/02/2022
  2052                              <1> ; ----------------------------------------------------------------------------
  2053                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2054                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2055                              <1> ;
  2056                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2057                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2058                              <1> ; <Bell Laboratories (17/3/1972)>
  2059                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2060                              <1> ;
  2061                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2062                              <1> ;
  2063                              <1> ; ****************************************************************************
  2064                              <1> ; 15/09/2015
  2065                              <1> 
  2066                              <1> tswitch: ; Retro UNIX 386 v1
  2067                              <1> tswap:
  2068                              <1> 	; 01/09/2015
  2069                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2070                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2071                              <1> 	; time out swap, called when a user times out.
  2072                              <1> 	; the user is put on the low priority queue.
  2073                              <1> 	; This is done by making a link from the last user
  2074                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2075                              <1> 	; then he is swapped out.
  2076                              <1> 	;
  2077                              <1> 	; Retro UNIX 386 v1 modification ->
  2078                              <1> 	;       swap (software task switch) is performed by changing
  2079                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2080                              <1> 	;	as in Retro UNIX 8086 v1.
  2081                              <1> 	;
  2082                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2083                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2084                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2085                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2086                              <1> 	;	compatibles was using 1MB segmented memory 
  2087                              <1> 	;	in 8086/8088 times.
  2088                              <1> 	;
  2089                              <1> 	; INPUTS ->
  2090                              <1> 	;    u.uno - users process number
  2091                              <1> 	;    runq+4 - lowest priority queue
  2092                              <1> 	; OUTPUTS ->
  2093                              <1> 	;    r0 - users process number
  2094                              <1> 	;    r2 - lowest priority queue address
  2095                              <1> 	;
  2096                              <1> 	; ((AX = R0, BX = R2)) output
  2097                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2098                              <1> 	;
  2099 00004E87 A0[A56F0000]        <1> 	mov 	al, [u.uno]
  2100                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2101                              <1> 		; mov  $runq+4,r2 
  2102                              <1> 			; / move lowest priority queue address to r2
  2103 00004E8C E8CD000000          <1>         call 	putlu
  2104                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2105                              <1> 		             ; / u.uno's user
  2106                              <1> 
  2107                              <1> switch: ; Retro UNIX 386 v1
  2108                              <1> swap:
  2109                              <1> 	; 03/02/2022
  2110                              <1> 	; 02/09/2015
  2111                              <1> 	; 01/09/2015
  2112                              <1> 	; 31/08/2015
  2113                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2114                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2115                              <1> 	; 'swap' is routine that controls the swapping of processes
  2116                              <1> 	; in and out of core.
  2117                              <1> 	;
  2118                              <1> 	; Retro UNIX 386 v1 modification ->
  2119                              <1> 	;       swap (software task switch) is performed by changing
  2120                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2121                              <1> 	;	as in Retro UNIX 8086 v1.
  2122                              <1> 	;
  2123                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2124                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2125                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2126                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2127                              <1> 	;	compatibles was using 1MB segmented memory 
  2128                              <1> 	;	in 8086/8088 times.
  2129                              <1> 	;
  2130                              <1> 	; INPUTS ->
  2131                              <1> 	;    runq table - contains processes to run.
  2132                              <1> 	;    p.link - contains next process in line to be run.
  2133                              <1> 	;    u.uno - process number of process in core	
  2134                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2135                              <1> 	; OUTPUTS ->
  2136                              <1> 	;    (original unix v1 -> present process to its disk block)
  2137                              <1> 	;    (original unix v1 -> new process into core -> 
  2138                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2139                              <1> 	;	   for new process)
  2140                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2141                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2142                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2143                              <1> 	;	 for now, it will swap the process if there is not
  2144                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2145                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2146                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2147                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2148                              <1> 	;
  2149                              <1> 	;    u.pri -points to highest priority run Q.
  2150                              <1> 	;    r2 - points to the run queue.
  2151                              <1> 	;    r1 - contains new process number
  2152                              <1> 	;    r0 - points to place in routine or process that called
  2153                              <1> 	;	  swap all user parameters
  2154                              <1> 	;				
  2155                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2156                              <1> 	;
  2157                              <1> swap_0:
  2158                              <1> 		;mov $300,*$ps / processor priority = 6
  2159 00004E91 BE[4E6F0000]        <1> 	mov	esi, runq
  2160                              <1> 		; mov $runq,r2 / r2 points to runq table
  2161                              <1> swap_1: ; 1: / search runq table for highest priority process
  2162 00004E96 668B06              <1> 	mov	ax, [esi]
  2163 00004E99 6621C0              <1> 	and 	ax, ax
  2164                              <1>        		; tst (r2)+ / are there any processes to run 
  2165                              <1> 			  ; / in this Q entry
  2166 00004E9C 7507                <1> 	jnz	short swap_2
  2167                              <1>        		; bne 1f / yes, process 1f
  2168                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2169                              <1> 			       ; / to end of table
  2170                              <1> 		; bne 1b / if not at end, go back
  2171 00004E9E E8E0000000          <1> 	call	idle
  2172                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2173                              <1> 				       ; / all queues are empty
  2174 00004EA3 EBF1                <1> 	jmp	short swap_1
  2175                              <1> 		; br swap
  2176                              <1> swap_2: ; 1:
  2177 00004EA5 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2178                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2179                              <1>  		; mov r2,u.pri / set present user to this run queue
  2180                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2181 00004EA8 38E0                <1> 	cmp	al, ah
  2182                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2183                              <1> 			      ; / in this Q to be run
  2184 00004EAA 740A                <1> 	je	short swap_3
  2185                              <1>        		; beq 1f / yes
  2186                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2187                              <1> 	;movzx	ebx, al
  2188 00004EAC 8AA3[C76C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2189 00004EB2 8826                <1>        	mov	[esi], ah
  2190                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2191                              <1> 				       ; / in line into run queue
  2192 00004EB4 EB05                <1> 	jmp	short swap_4
  2193                              <1>        		; br 2f
  2194                              <1> swap_3: ; 1:
  2195                              <1> 	;xor	dx, dx
  2196                              <1> 	; 03/02/2022
  2197 00004EB6 31D2                <1> 	xor	edx, edx
  2198 00004EB8 668916              <1> 	mov	[esi], dx
  2199                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2200                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2201                              <1>       ; / in new process if required
  2202                              <1>        		; clr *$ps / clear processor status
  2203 00004EBB 8A25[A56F0000]      <1> 	mov 	ah, [u.uno]
  2204 00004EC1 38C4                <1> 	cmp	ah, al
  2205                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2206                              <1> 			      ; / the process in core?
  2207 00004EC3 743B                <1>        	je	short swap_8
  2208                              <1>        		; beq 2f / yes, don't have to swap
  2209                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2210                              <1> 			   ; / (address in routine that called swap)
  2211                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2212                              <1> 	; 01/09/2015
  2213                              <1> 	;mov	[u.usp], esp
  2214                              <1>        		; mov sp,u.usp / save stack pointer
  2215                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2216                              <1> 			       ; / to the stack pointer
  2217 00004EC5 08E4                <1> 	or	ah, ah
  2218                              <1>        		; tstb u.uno / is the process # = 0
  2219 00004EC7 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2220                              <1> 		; beq  1f / yes, kill process by overwriting
  2221                              <1> 	; 02/09/2015
  2222 00004EC9 8925[586F0000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2223                              <1> 	;
  2224 00004ECF E834000000          <1> 	call	wswap
  2225                              <1> 		;jsr r0,wswap / write out core to disk
  2226                              <1> 	 ; 31/08/2015
  2227                              <1> 	;movzx	ebx, al ; New (running) process number
  2228 00004ED4 EB1C                <1> 	jmp 	short swap_7
  2229                              <1> swap_6:
  2230                              <1> 	; 31/08/2015
  2231                              <1> 	; Deallocate memory pages belong to the process
  2232                              <1> 	; which is being terminated
  2233                              <1> 	; 14/05/2015 ('sysexit')
  2234                              <1>  	; Deallocate memory pages of the process
  2235                              <1> 	; (Retro UNIX 386 v1 modification !)
  2236                              <1> 	;
  2237                              <1> 	; movzx ebx, al
  2238 00004ED6 53                  <1> 	push	ebx
  2239 00004ED7 A1[AF6F0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2240 00004EDC 8B1D[B36F0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2241 00004EE2 E81DE0FFFF          <1> 	call	deallocate_page_dir
  2242 00004EE7 A1[A66F0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2243 00004EEC E8ABE0FFFF          <1> 	call	deallocate_page
  2244 00004EF1 5B                  <1> 	pop	ebx
  2245                              <1> swap_7: ;1: 
  2246                              <1> 	; 02/09/2015
  2247                              <1> 	; 31/08/2015
  2248                              <1> 	; 14/05/2015
  2249 00004EF2 C0E302              <1> 	shl	bl, 2 ; * 4 
  2250 00004EF5 8B83[E46C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2251                              <1> 	;cli
  2252 00004EFB E831000000          <1> 	call	rswap
  2253                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2254                              <1> 		; jsr r0,rswap / read new process into core
  2255                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2256                              <1> 			      ; / to his program to its normal
  2257                              <1> 	; 01/09/2015
  2258                              <1> 	;mov	esp, [u.usp]	
  2259                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2260                              <1> 			     ; / new process stack
  2261                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2262                              <1> 			     ; / that just got swapped in, left off.,
  2263                              <1> 			     ; / i.e., transfer control to new process
  2264                              <1> 	;sti
  2265                              <1> swap_8: ;2:
  2266                              <1> 	; RETRO UNIX 8086 v1 modification !
  2267 00004F00 C605[986F0000]04    <1> 	mov	byte [u.quant], time_count 
  2268                              <1> 		; movb $30.,uquant / initialize process time quantum
  2269 00004F07 C3                  <1> 	retn
  2270                              <1> 		; rts r0 / return
  2271                              <1> 
  2272                              <1> wswap:  ; < swap out, swap to disk >
  2273                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2274                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2275                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2276                              <1> 	; appropriate disk area.
  2277                              <1> 	;
  2278                              <1> 	; Retro UNIX 386 v1 modification ->
  2279                              <1> 	;       User (u) structure content and the user's register content
  2280                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2281                              <1> 	;	saving 'u' structure and user registers for task switching).
  2282                              <1> 	;	u.usp - points to kernel stack address which contains
  2283                              <1> 	;		user's registers while entering system call.  
  2284                              <1> 	;	u.sp  - points to kernel stack address 
  2285                              <1> 	;		to return from system call -for IRET-.
  2286                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2287                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2288                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2289                              <1> 	;
  2290                              <1> 	; Retro UNIX 8086 v1 modification ->
  2291                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2292                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2293                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2294                              <1> 	;	compatibles was using 1MB segmented memory 
  2295                              <1> 	;	in 8086/8088 times.
  2296                              <1> 	;
  2297                              <1> 	; INPUTS ->
  2298                              <1> 	;    u.break - points to end of program
  2299                              <1> 	;    u.usp - stack pointer at the moment of swap
  2300                              <1> 	;    core - beginning of process program		
  2301                              <1> 	;    ecore - end of core 	
  2302                              <1> 	;    user - start of user parameter area		
  2303                              <1> 	;    u.uno - user process number	
  2304                              <1> 	;    p.dska - holds block number of process	
  2305                              <1> 	; OUTPUTS ->
  2306                              <1> 	;    swp I/O queue
  2307                              <1> 	;    p.break - negative word count of process 
  2308                              <1> 	;    r1 - process disk address	
  2309                              <1> 	;    r2 - negative word count
  2310                              <1> 	;
  2311                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2312                              <1> 	;
  2313                              <1> 	; INPUTS ->
  2314                              <1> 	;    u.uno - process number (to be swapped out)
  2315                              <1> 	; OUTPUTS ->
  2316                              <1> 	;    none
  2317                              <1> 	;
  2318                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2319                              <1> 	;
  2320 00004F08 8B3D[A66F0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2321 00004F0E B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2322 00004F13 BE[546F0000]        <1> 	mov	esi, user ; active user (u) structure	
  2323 00004F18 F3A5                <1> 	rep	movsd
  2324                              <1> 	;
  2325 00004F1A 8B35[586F0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2326                              <1> 			     ;      points to user registers)
  2327 00004F20 8B0D[546F0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2328                              <1> 			     ; (for IRET)
  2329                              <1> 			     ; [u.sp] -> EIP (user)
  2330                              <1> 			     ; [u.sp+4]-> CS (user)
  2331                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2332                              <1> 			     ; [u.sp+12] -> ESP (user)
  2333                              <1> 			     ; [u.sp+16] -> SS (user)	
  2334 00004F26 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2335 00004F28 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2336                              <1> 			     ; (for IRET) 	
  2337 00004F2B C1E902              <1> 	shr	ecx, 2	     		
  2338 00004F2E F3A5                <1> 	rep	movsd
  2339 00004F30 C3                  <1> 	retn
  2340                              <1> 
  2341                              <1> 	; Original UNIX v1 'wswap' routine:
  2342                              <1> 	; wswap:
  2343                              <1> 		; mov *$30,u.emt / determines handling of emts
  2344                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2345                              <1> 				; / illegal instructions
  2346                              <1> 		; mov u.break,r2 / put process program break address in r2
  2347                              <1> 		; inc r2 / add 1 to it 
  2348                              <1> 		; bic $1,r2 / make it even
  2349                              <1> 		; mov r2,u.break / set break to an even location
  2350                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2351                              <1> 			     ; / at moment of swap in r3
  2352                              <1> 		; cmp r2,$core / is u.break less than $core
  2353                              <1> 		; blos 2f / yes
  2354                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2355                              <1>        		; bhis 2f / yes
  2356                              <1> 	; 1:
  2357                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2358                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2359                              <1> 		; bne 1b / no, keep packing
  2360                              <1> 	 	; br 1f / yes
  2361                              <1> 	; 2:
  2362                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2363                              <1> 	; 1:
  2364                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2365                              <1> 			   ; / (user up to end of stack gets written out)
  2366                              <1> 		; neg r2 / make it negative
  2367                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2368                              <1> 		; mov r2,swp+4 / word count
  2369                              <1> 		; movb u.uno,r1 / move user process number to r1
  2370                              <1> 		; asl r1 / x2 for index
  2371                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2372                              <1> 				     ; / into the p.break table
  2373                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2374                              <1> 				    ; /	for process to r1
  2375                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2376                              <1> 			     ; / (block number)
  2377                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2378                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2379                              <1> 	; 1:
  2380                              <1>        		; tstb swp+1 / is lt done writing?
  2381                              <1>        		; bne 1b / no, wait
  2382                              <1> 		; rts r0 / yes, return to swap
  2383                              <1> 
  2384                              <1> rswap:  ; < swap in, swap from disk >
  2385                              <1> 	; 15/09/2015
  2386                              <1> 	; 28/08/2015
  2387                              <1> 	; 14/05/2015
  2388                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2389                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2390                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2391                              <1> 	; from disk into core.
  2392                              <1> 	;
  2393                              <1> 	; Retro UNIX 386 v1 modification ->
  2394                              <1> 	;       User (u) structure content and the user's register content
  2395                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2396                              <1> 	;	saving 'u' structure and user registers for task switching).
  2397                              <1> 	;	u.usp - points to kernel stack address which contains
  2398                              <1> 	;		user's registers while entering system call.  
  2399                              <1> 	;	u.sp  - points to kernel stack address 
  2400                              <1> 	;		to return from system call -for IRET-.
  2401                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2402                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2403                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2404                              <1> 	;
  2405                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2406                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2407                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2408                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2409                              <1> 	;	compatibles was using 1MB segmented memory 
  2410                              <1> 	;	in 8086/8088 times.
  2411                              <1> 	;
  2412                              <1> 	; INPUTS ->
  2413                              <1> 	;    r1 - process number of process to be read in
  2414                              <1> 	;    p.break - negative of word count of process 
  2415                              <1> 	;    p.dska - disk address of the process		
  2416                              <1> 	;    u.emt - determines handling of emt's 	
  2417                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2418                              <1> 	; OUTPUTS ->
  2419                              <1> 	;    8 = (u.ilgins)
  2420                              <1> 	;    24 = (u.emt)
  2421                              <1> 	;    swp - bit 10 is set to indicate read 
  2422                              <1> 	;		(bit 15=0 when reading is done)	
  2423                              <1> 	;    swp+2 - disk block address
  2424                              <1> 	;    swp+4 - negative word count 	
  2425                              <1> 	;      ((swp+6 - address of user structure)) 
  2426                              <1> 	;
  2427                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2428                              <1> 	;
  2429                              <1> 	; INPUTS ->
  2430                              <1> 	;    AL	- new process number (to be swapped in)	 
  2431                              <1> 	; OUTPUTS ->
  2432                              <1> 	;    none
  2433                              <1> 	;
  2434                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2435                              <1> 	;
  2436                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2437 00004F31 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2438 00004F33 B91C000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2439 00004F38 BF[546F0000]        <1> 	mov	edi, user ; active user (u) structure	
  2440 00004F3D F3A5                <1> 	rep	movsd
  2441 00004F3F 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2442 00004F40 8B3D[586F0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2443                              <1> 			     ;      points to user registers)
  2444 00004F46 8B0D[546F0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2445                              <1> 			     ; (for IRET)
  2446                              <1> 			     ; [u.sp] -> EIP (user)
  2447                              <1> 			     ; [u.sp+4]-> CS (user)
  2448                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2449                              <1> 			     ; [u.sp+12] -> ESP (user)
  2450                              <1> 			     ; [u.sp+16] -> SS (user)		
  2451                              <1> 	; 28/08/2015
  2452 00004F4C 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2453 00004F4E 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2454                              <1> 			     ; (for IRET) 	
  2455 00004F51 C1E902              <1> 	shr	ecx, 2	       		
  2456 00004F54 F3A5                <1> 	rep	movsd
  2457 00004F56 8B25[586F0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2458 00004F5C 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2459 00004F5D C3                  <1> 	retn
  2460                              <1> 
  2461                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2462                              <1> 	;rswap:
  2463                              <1>        		; asl r1 / process number x2 for index
  2464                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2465                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2466                              <1>        		; bis $2000,swp / read
  2467                              <1>        		; jsr r0,ppoke / read it in 
  2468                              <1> 	; 1:
  2469                              <1>        		; tstb swp+1 / done
  2470                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2471                              <1>        		; mov u.emt,*$30 / yes move these
  2472                              <1>        		; mov u.ilgins,*$10 / back
  2473                              <1>        		; rts r0 / return
  2474                              <1> 
  2475                              <1> 	;unpack: ; / move stack back to its normal place
  2476                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2477                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2478                              <1> 		; blos 2f / yes, return
  2479                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2480                              <1> 			     ; / before swapping
  2481                              <1> 		; bhis 2f / yes, return
  2482                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2483                              <1> 		; add r3,r2
  2484                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2485                              <1> 	; 1:
  2486                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2487                              <1> 		; cmp r2,u.break / in core
  2488                              <1> 		; bne 1b
  2489                              <1> 	; 2:
  2490                              <1>        		; rts r0
  2491                              <1> 
  2492                              <1> putlu: 
  2493                              <1> 	; 12/09/2015
  2494                              <1> 	; 02/09/2015
  2495                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2496                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2497                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2498                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2499                              <1> 	; the last process on the queue to process in r1 by putting
  2500                              <1> 	; the process number in r1 into the last process's link.
  2501                              <1> 	;
  2502                              <1> 	; INPUTS ->
  2503                              <1> 	;    r1 - user process number
  2504                              <1> 	;    r2 - points to lowest priority queue 
  2505                              <1> 	;    p.dska - disk address of the process		
  2506                              <1> 	;    u.emt - determines handling of emt's 	
  2507                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2508                              <1> 	; OUTPUTS ->
  2509                              <1> 	;    r3 - process number of last process on the queue upon
  2510                              <1> 	;	  entering putlu
  2511                              <1> 	;    p.link-1 + r3 - process number in r1
  2512                              <1> 	;    r2 - points to lowest priority queue
  2513                              <1> 	;
  2514                              <1> 	; ((Modified registers: EDX, EBX)) 
  2515                              <1> 	;
  2516                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2517                              <1> 
  2518                              <1> 	; eBX = r2
  2519                              <1> 	; eAX = r1 (AL=r1b)
  2520                              <1> 
  2521 00004F5E BB[4E6F0000]        <1> 	mov	ebx, runq
  2522 00004F63 0FB613              <1> 	movzx  	edx, byte [ebx]
  2523 00004F66 43                  <1> 	inc	ebx
  2524 00004F67 20D2                <1> 	and	dl, dl
  2525                              <1> 		; tstb (r2)+ / is queue empty?
  2526 00004F69 740A                <1>        	jz	short putlu_1
  2527                              <1> 		; beq 1f / yes, branch
  2528 00004F6B 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2529                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2530                              <1> 			     ; / in r3
  2531 00004F6D 8882[C76C0000]      <1>        	mov	[edx+p.link-1], al
  2532                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2533                              <1> 			     ; / "last users" link
  2534 00004F73 EB03                <1> 	jmp	short putlu_2
  2535                              <1> 		; br 2f /
  2536                              <1> putlu_1: ; 1:
  2537 00004F75 8843FF              <1> 	mov	[ebx-1], al
  2538                              <1>        		; movb r1,-1(r2) / user is only user; 
  2539                              <1> 			    ; / put process no. at beginning and at end
  2540                              <1> putlu_2: ; 2: 
  2541 00004F78 8803                <1> 	mov	[ebx], al
  2542                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2543                              <1> 			     ; / on the queue
  2544 00004F7A 88C2                <1> 	mov	dl, al
  2545 00004F7C 88B2[C76C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2546                              <1> 		; dec r2 / restore r2
  2547 00004F82 C3                  <1>         retn
  2548                              <1> 		; rts r0
  2549                              <1> 
  2550                              <1> ;copyz:
  2551                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2552                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2553                              <1> ;       mov     (r0)+,r1
  2554                              <1> ;       mov     (r0)+,r2
  2555                              <1> ;1:
  2556                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2557                              <1> ;       cmp     r1,r2 
  2558                              <1> ;       blo     1b
  2559                              <1> ;       mov     (sp)+,r2 / restore r2
  2560                              <1> ;       mov     (sp)+,r1 / restore r1
  2561                              <1> ;       rts     r0 
  2562                              <1> 
  2563                              <1> idle:
  2564                              <1> 	; 01/09/2015
  2565                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2566                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2567                              <1> 	; (idle & wait loop)
  2568                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2569                              <1> 	; idle procedure!
  2570                              <1>       	;
  2571                              <1>   	; 01/09/2015
  2572 00004F83 FB                  <1> 	sti
  2573                              <1>       	; 29/07/2013
  2574 00004F84 F4                  <1>       	hlt
  2575 00004F85 90                  <1>       	nop ; 10/10/2013
  2576 00004F86 90                  <1>       	nop
  2577 00004F87 90                  <1>       	nop
  2578                              <1>       	; 23/10/2013
  2579 00004F88 90                  <1>       	nop
  2580 00004F89 90                  <1>       	nop
  2581 00004F8A 90                  <1>       	nop
  2582 00004F8B 90                  <1>       	nop
  2583 00004F8C C3                  <1>       	retn      
  2584                              <1> 
  2585                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2586                              <1> 	;clr *$ps / clear ps
  2587                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2588                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2589                              <1> 	;1 / wait for interrupt
  2590                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2591                              <1> 	;mov (sp)+,*$ps
  2592                              <1> 	;rts r0
  2593                              <1> 
  2594                              <1> clear:
  2595                              <1> 	; 03/02/2022
  2596                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2597                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2598                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2599                              <1> 	; on the current device (cdev)
  2600                              <1> 	;	
  2601                              <1> 	; INPUTS ->
  2602                              <1> 	;    r1 - block number of block to be zeroed
  2603                              <1> 	;    cdev - current device number 
  2604                              <1> 	; OUTPUTS ->
  2605                              <1> 	;    a zeroed I/O buffer onto the current device
  2606                              <1> 	;    r1 - points to last entry in the I/O buffer
  2607                              <1> 	;
  2608                              <1> 	; ((AX = R1)) input/output
  2609                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2610                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2611                              <1> 
  2612 00004F8D E80E0E0000          <1> 	call 	wslot
  2613                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2614                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2615 00004F92 89DF                <1> 	mov	edi, ebx ; r5
  2616 00004F94 89C2                <1> 	mov	edx, eax
  2617 00004F96 B980000000          <1> 	mov	ecx, 128
  2618                              <1> 		; mov $256.,r3
  2619 00004F9B 31C0                <1> 	xor	eax, eax
  2620 00004F9D F3AB                <1> 	rep	stosd
  2621 00004F9F 89D0                <1> 	mov	eax, edx
  2622                              <1> ; 1: 
  2623                              <1>        		; clr (r5)+ / zero data word in buffer
  2624                              <1>        		; dec r3
  2625                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2626                              <1> 	;call	dskwr
  2627                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2628                              <1>                              ; / block specified in r1
  2629                              <1> 	; eAX (r1) = block number
  2630                              <1> 	;retn
  2631                              <1> 		; rts r0
  2632                              <1> 	; 03/02/2022
  2633 00004FA1 E9160E0000          <1> 	jmp	dskwr
  2050                                  %include 'u4.s'        ; 15/04/2015
  2051                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2052                              <1> ; Last Modification: 26/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 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2063                              <1> ;
  2064                              <1> ; ****************************************************************************
  2065                              <1> ; 14/10/2015
  2066                              <1> 
  2067                              <1> ;setisp:
  2068                              <1>        ;mov     r1,-(sp)
  2069                              <1>        ;mov     r2,-(sp)
  2070                              <1>        ;mov     r3,-(sp)
  2071                              <1>        ;mov     clockp,-(sp)
  2072                              <1>        ;mov     $s.syst+2,clockp
  2073                              <1>        ;jmp     (r0)
  2074                              <1> 
  2075                              <1> clock: ; / interrupt from 60 cycle clock
  2076                              <1> 	
  2077                              <1> 	; 14/10/2015
  2078                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2079                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2080                              <1> 
  2081                              <1>        ;mov     r0,-(sp) / save r0
  2082                              <1>        ;tst     *$lks / restart clock?
  2083                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2084                              <1>        ;inc     (r0)
  2085                              <1>        ;bne     1f
  2086                              <1>        ;inc     -(r0)
  2087                              <1> ;1:
  2088                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2089                              <1>        ;inc     (r0)
  2090                              <1>        ;bne     1f
  2091                              <1>        ;inc     -(r0)
  2092                              <1> ;1:
  2093                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2094                              <1> 
  2095 00004FA6 803D[986F0000]00    <1> 	cmp	byte [u.quant], 0
  2096 00004FAD 772C                <1> 	ja	short clk_1
  2097                              <1> 	;
  2098 00004FAF 803D[536F0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2099 00004FB6 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2100 00004FB8 803D[A56F0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2101 00004FBF 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2102 00004FC1 66833D[9A6F0000]00  <1> 	cmp	word [u.intr], 0
  2103 00004FC9 7616                <1> 	jna	short clk_2
  2104                              <1> clk_0:
  2105                              <1> 	; 14/10/2015
  2106 00004FCB FE05[536F0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2107 00004FD1 58                  <1> 	pop	eax ; return address to the timer interrupt
  2108                              <1> 	;
  2109 00004FD2 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2110                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2111 00004FD4 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2112                              <1> 	;
  2113 00004FD6 E97CEBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2114                              <1> clk_1:
  2115 00004FDB FE0D[986F0000]      <1> 	dec	byte [u.quant]
  2116                              <1> clk_2:
  2117 00004FE1 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2118                              <1> 
  2119                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2120                              <1> 
  2121                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2122                              <1>        ;decb    (r0)
  2123                              <1>        ;bge     1f / if less than 0
  2124                              <1>        ;clrb    (r0) / make it 0
  2125                              <1> ;1: / decrement time out counts return now if priority was not 0
  2126                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2127                              <1>        ;bge     2f / yes, check time outs
  2128                              <1>        ;tstb    (r0) / no, user timed out?
  2129                              <1>        ;bne     1f / no
  2130                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2131                              <1>        ;bne     1f / no, 1f
  2132                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2133                              <1>        ;sys     0 / sysrele
  2134                              <1>        ;rti
  2135                              <1> ;2: / priority is high so just decrement time out counts
  2136                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2137                              <1> ;2:
  2138                              <1>        ;tstb    (r0) / is the time out?
  2139                              <1>        ;beq     3f / yes, 3f (get next entry)
  2140                              <1>        ;decb    (r0) / no, decrement the time
  2141                              <1>        ;bne     3f / isit zero now?
  2142                              <1>        ;incb    (r0) / yes, increment the time
  2143                              <1> ;3:
  2144                              <1>        ;inc     r0 / next entry
  2145                              <1>        ;cmp     r0,$touts / end of toutt table?
  2146                              <1>        ;blo     2b / no, check this entry
  2147                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2148                              <1>        ;rti / return from interrupt
  2149                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2150                              <1>        ;mov     (sp)+,r0 / restore r0
  2151                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2152                              <1>        ;jsr     r0,setisp / save registers
  2153                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2154                              <1>                                ;  / the table
  2155                              <1> ;1:
  2156                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2157                              <1>        ;beq     2f / yes
  2158                              <1>        ;decb    toutt(r0) / no, decrement the time
  2159                              <1>        ;bne     2f / is the time 0, now
  2160                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2161                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2162                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2163                              <1> ;2:
  2164                              <1>        ;dec     r0 / set up r0 for next entry
  2165                              <1>        ;bge     1b / finished? , no, go back
  2166                              <1>        ;br      retisp / yes, restore registers and do a rti
  2167                              <1> 
  2168                              <1> ;retisp:
  2169                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2170                              <1>        ;mov     (sp)+,r3
  2171                              <1>        ;mov     (sp)+,r2
  2172                              <1>        ;mov     (sp)+,r1
  2173                              <1>        ;mov     (sp)+,r0
  2174                              <1>        ;rti     / return from interrupt
  2175                              <1> 
  2176                              <1> 
  2177                              <1> wakeup: ; / wakeup processes waiting for an event 
  2178                              <1> 	; / by linking them to the queue
  2179                              <1> 	;
  2180                              <1> 	; 26/02/2022
  2181                              <1> 	; 15/09/2015
  2182                              <1> 	; 29/06/2015
  2183                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2184                              <1> 	;
  2185                              <1> 	; 15/05/2013 - 02/06/2014
  2186                              <1> 	; Retro UNIX 8086 v1 modification !
  2187                              <1> 	; (Process/task switching routine by using
  2188                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2189                              <1> 	;
  2190                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2191                              <1> 	; sleeping in the specified wait channel by creating a link 
  2192                              <1> 	; to it from the last user process on the run queue.
  2193                              <1> 	; If there is no process to wake up, nothing happens.
  2194                              <1> 	;
  2195                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2196                              <1> 	; 'switching' status of the current process (owns current tty)
  2197                              <1> 	; (via alt + function keys) to a process which has highest
  2198                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2199                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2200                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2201                              <1> 	; tty for tty switching by keyboard.)	 
  2202                              <1> 	; 
  2203                              <1> 	; INPUT -> 
  2204                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2205                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2206                              <1> 	;
  2207                              <1> 	; ((modified registers: EAX, EBX))
  2208                              <1> 	;
  2209 00004FE2 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2210 00004FE5 81C3[F86B0000]      <1> 	add	ebx, wlist
  2211 00004FEB 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2212 00004FED 20C0                <1> 	and	al, al
  2213 00004FEF 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2214                              <1> 	;
  2215 00004FF1 30E4                <1> 	xor	ah, ah
  2216 00004FF3 8825[986F0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2217 00004FF9 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2218                              <1> 	; 15/09/2015
  2219 00004FFB 0FB6D8              <1> 	movzx	ebx, al
  2220                              <1> 	; 26/02/2022 (p.waitc is not used)
  2221                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2222 00004FFE FEC4                <1> 	inc	ah
  2223 00005000 88A3[D76C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2224                              <1> 	;
  2225 00005006 57                  <1> 	push	edi
  2226 00005007 52                  <1> 	push	edx
  2227 00005008 E851FFFFFF          <1> 	call	putlu
  2228 0000500D 5A                  <1> 	pop	edx
  2229 0000500E 5F                  <1> 	pop	edi
  2230                              <1> wa0:
  2231 0000500F C3                  <1> 	retn
  2232                              <1> 
  2233                              <1> sleep: 
  2234                              <1> 	; 26/02/2022
  2235                              <1> 	; 03/02/2022
  2236                              <1> 	; 15/09/2015
  2237                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2238                              <1> 	;
  2239                              <1> 	; 09/05/2013 - 20/03/2014
  2240                              <1> 	;
  2241                              <1> 	; Retro UNIX 8086 v1 modification !
  2242                              <1> 	; (Process/task switching and quit routine by using
  2243                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2244                              <1> 	;
  2245                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2246                              <1> 	; tty and tape output or input becomes available
  2247                              <1> 	; and process is put on waiting channel and swapped out,
  2248                              <1> 	; then -when the tty or tape is ready to write or read-
  2249                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2250                              <1> 	;
  2251                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2252                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2253                              <1> 	; status of the current process also INT 1Ch will count down
  2254                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2255                              <1> 	; to tty buffer of the current process and kernel will get
  2256                              <1> 	; user input by using tty buffer of the current process
  2257                              <1> 	; (instead of standard INT 16h interrupt).
  2258                              <1> 	; TTY output will be redirected to related video page of text mode
  2259                              <1> 	; (INT 10h will be called with different video page depending
  2260                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2261                              <1> 	; pseudo screens.)
  2262                              <1> 	;
  2263                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2264                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2265                              <1> 	; characters/data on serial port(s).
  2266                              <1> 	;
  2267                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2268                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2269                              <1> 	; 
  2270                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2271                              <1> 	;
  2272                              <1> 	;; 05/10/2013
  2273                              <1>         ;10/12/2013
  2274                              <1> 	;cmp   byte [u.uno], 1
  2275                              <1>         ;ja    short sleep0
  2276                              <1> 	;retn
  2277                              <1> 
  2278                              <1> 	; 20/03/2014
  2279                              <1> 	;mov	bx, [runq]
  2280                              <1> 	;cmp	bl, bh
  2281                              <1> 	;jne	short sleep0	
  2282                              <1> 	; 25/02/2014
  2283                              <1> 	;cmp word ptr [runq], 0
  2284                              <1> 	;ja short sleep0	
  2285                              <1> 	;retn
  2286                              <1> sleep0:
  2287                              <1> 	;
  2288 00005010 E849000000          <1> 	call	isintr
  2289                              <1> 	;jnz	sysret
  2290                              <1> 		; / wait for event
  2291                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2292                              <1> 			      ; / or quit from user
  2293                              <1>                		; br 2f / something happened
  2294                              <1> 			      ; / yes, his interrupt so return
  2295                              <1>                      	      ;	/ to user
  2296                              <1> 	; 03/02/2022
  2297 00005015 7405                <1> 	jz	short sleep_2
  2298                              <1> sleep_3:
  2299 00005017 E9DFEAFFFF          <1> 	jmp	sysret
  2300                              <1> sleep_2:
  2301                              <1> 	; 30/06/2015
  2302 0000501C 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2303 0000501F 81C3[F86B0000]      <1> 	add	ebx, wlist
  2304 00005025 8A03                <1> 	mov	al, [ebx]
  2305 00005027 20C0                <1> 	and	al, al
  2306 00005029 7407                <1> 	jz	short sleep1
  2307 0000502B 53                  <1> 	push	ebx
  2308 0000502C E82DFFFFFF          <1> 	call	putlu
  2309 00005031 5B                  <1> 	pop	ebx
  2310                              <1> sleep1:
  2311 00005032 A0[A56F0000]        <1> 	mov	al, [u.uno]    
  2312 00005037 8803                <1>   	mov	[ebx], al 	; put the process number
  2313                              <1> 				; in the wait channel
  2314                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2315                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2316                              <1> 				     ; / on the stack
  2317                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2318                              <1> 				     ; / to put to sleep in there
  2319                              <1>         ; 15/09/2015
  2320 00005039 0FB6D8              <1> 	movzx	ebx, al
  2321 0000503C C683[D76C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2322                              <1> 	; 26/02/2022 (p.waitc is not used)
  2323                              <1> 	;inc	ah
  2324                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2325                              <1> 	;
  2326 00005043 66FF35[406F0000]    <1> 	push    word [cdev]
  2327                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2328 0000504A E842FEFFFF          <1> 	call	swap
  2329                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2330 0000504F 668F05[406F0000]    <1>         pop     word [cdev]
  2331                              <1> 		; mov (sp)+,cdev / restore device
  2332 00005056 E803000000          <1> 	call	isintr
  2333                              <1> 	; 22/09/2013
  2334                              <1> 	;jnz	sysret         
  2335                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2336                              <1>                		; br 2f / yes, return to new user
  2337                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2338                              <1> 				; / originally on the wait channel
  2339                              <1>        		; beq 1f / if 0 branch
  2340                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2341                              <1>        		; mov $300,*$ps / processor priority = 6
  2342                              <1> 		; jsr r0,putlu / create link to old process number
  2343                              <1>        		; clr *$ps / clear the status; process priority = 0
  2344                              <1> 	; 03/02/2022
  2345 0000505B 75BA                <1> 	jnz	short sleep_3
  2346                              <1>      ;1:
  2347 0000505D C3                  <1> 	retn
  2348                              <1> 		; rts r0 / return
  2349                              <1>      ;2:
  2350                              <1>         ;;jmp	sysret
  2351                              <1> 		; jmp sysret / return to user
  2352                              <1> 
  2353                              <1> isintr:
  2354                              <1> 	; 03/02/2022
  2355                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2356                              <1> 	;
  2357                              <1> 	; 09/05/2013 - 30/05/2014
  2358                              <1> 	;
  2359                              <1> 	; Retro UNIX 8086 v1 modification !
  2360                              <1> 	; (Process/task switching and quit routine by using
  2361                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2362                              <1> 	;
  2363                              <1> 	; Retro UNIX 8086 v1 modification:
  2364                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2365                              <1> 	;  and there is a 'quit' request by user;
  2366                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2367                              <1> 	;  "nothing to do". (20/10/2013)
  2368                              <1> 	;
  2369                              <1> 	; 20/10/2013
  2370 0000505E 66833D[8C6F0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2371 00005066 761F                <1> 	jna	short isintr2 ; retn
  2372                              <1> 	; 03/09/2013
  2373                              <1> 	; (nothing to do)
  2374                              <1> 	;retn
  2375                              <1> 	; 22/09/2013
  2376 00005068 66833D[9A6F0000]00  <1> 	cmp	word [u.intr], 0
  2377 00005070 7615                <1> 	jna	short isintr2 ; retn
  2378                              <1> 	; 30/05/2014
  2379                              <1> 	;push	ax
  2380                              <1> 	; 03/02/2022
  2381 00005072 50                  <1> 	push	eax
  2382 00005073 66A1[9C6F0000]      <1> 	mov	ax, [u.quit]
  2383 00005079 6609C0              <1> 	or	ax, ax ; 0 ?
  2384 0000507C 7408                <1> 	jz	short isintr1 ; zf = 1
  2385 0000507E 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2386 00005082 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2387                              <1> 	;xor	ax, ax ; zf = 1
  2388                              <1> 	; 03/02/2022
  2389 00005084 31C0                <1> 	xor	eax, eax ; zf = 1
  2390                              <1> isintr1:
  2391                              <1> 	;pop	ax
  2392                              <1> 	; 03/02/2022
  2393 00005086 58                  <1> 	pop	eax
  2394                              <1> isintr2: ; 22/09/2013
  2395                              <1> 	; zf=1 -> nothing to do
  2396 00005087 C3                  <1> 	retn
  2397                              <1> 
  2398                              <1> 	; UNIX v1 original 'isintr' routine... 
  2399                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2400                              <1>        	;mov     r2,-(sp) / save r2
  2401                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2402                              <1>         ;                 / typewriter
  2403                              <1>        	;beq     1f / if 0, do nothing except skip return
  2404                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2405                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2406                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2407                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2408                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2409                              <1>         ;              / of interrupts
  2410                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2411                              <1>      ;1:
  2412                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2413                              <1>      ;4:
  2414                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2415                              <1>        	;mov     (sp)+,r1
  2416                              <1>        	;rts     r0
  2417                              <1>      ;3: / interrupt char = quit (fs)
  2418                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2419                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2420                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2421                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2422                              <1>      ;1: / find process control tty entry in tty block
  2423                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2424                              <1>        	;beq     1f / block found go to 1f
  2425                              <1>        	;add     $8,r1 / look at next tty block
  2426                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2427                              <1>        	;blo     1b / no
  2428                              <1>        	;br      4b / no process control tty found so go to 4b
  2429                              <1>      ;1:
  2430                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2431                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2432                              <1>         ;                  / identifier
  2433                              <1>        	;inc     0f / increment
  2434                              <1>      ;1:
  2435                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2436                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2437                              <1>         ;             / being typed out after you hit the interrupt
  2438                              <1>         ;             / key
  2439                              <1>        	;br      1b
  2051                                  %include 'u5.s'        ; 03/06/2015
  2052                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2053                              <1> ; Last Modification: 22/04/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 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2064                              <1> ;
  2065                              <1> ; ****************************************************************************
  2066                              <1> ; 14/11/2015
  2067                              <1> 
  2068                              <1> mget:
  2069                              <1> 	; 22/04/2022
  2070                              <1> 	; 03/02/2022
  2071                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2072                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2073                              <1> 	;
  2074                              <1> 	; Get existing or (allocate) a new disk block for file
  2075                              <1> 	; 
  2076                              <1> 	; INPUTS ->
  2077                              <1> 	;    u.fofp (file offset pointer)
  2078                              <1> 	;    inode 
  2079                              <1> 	;    u.off (file offset)
  2080                              <1> 	; OUTPUTS ->
  2081                              <1> 	;    r1 (physical block number)
  2082                              <1> 	;    r2, r3, r5 (internal)
  2083                              <1> 	;
  2084                              <1> 	; ((AX = R1)) output
  2085                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2086                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2087                              <1> 
  2088                              <1> 		; mov *u.fofp,mq / file offset in mq
  2089                              <1> 		; clr ac / later to be high sig
  2090                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2091                              <1> 		; mov mq,r2
  2092                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2093                              <1> 		; bne 4f / branch for large file
  2094                              <1> mget_0:	
  2095                              <1> 	; 03/02/2022
  2096 00005088 29C0                <1> 	sub	eax, eax
  2097 0000508A 29D2                <1> 	sub	edx, edx
  2098 0000508C 29C9                <1> 	sub	ecx, ecx
  2099 0000508E 29DB                <1> 	sub	ebx, ebx
  2100                              <1> 
  2101 00005090 8B35[6C6F0000]      <1>         mov     esi, [u.fofp]
  2102                              <1>         ;movzx	ebx, byte [esi+1]
  2103                              <1> 	; 03/02/2022
  2104 00005096 46                  <1> 	inc	esi
  2105 00005097 8A1E                <1> 	mov	bl, [esi]
  2106                              <1> 
  2107                              <1> 	; BX = r2
  2108                              <1> 	; 03/02/2022
  2109 00005099 F605[596C0000]10    <1> 	test	byte [i.flgs+1], 10h
  2110                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2111                              <1> 			  	     ; is this a large or small file
  2112 000050A0 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2113                              <1> 
  2114 000050A2 F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2115                              <1> 		; bit $!17,r2
  2116 000050A5 7525                <1> 	jnz 	short mget_2
  2117                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2118 000050A7 80E30E              <1>         and     bl, 0Eh  
  2119                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2120                              <1> 	; 03/02/2022
  2121 000050AA 668B83[5E6C0000]    <1> 	mov	ax, [ebx+i.dskp]
  2122                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2123                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2124                              <1> 	; 03/02/2022
  2125 000050B1 09C0                <1> 	or	eax, eax
  2126                              <1> 	;or 	ax, ax
  2127 000050B3 7516                <1> 	jnz 	short mget_1 
  2128                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2129                              <1> 		       ; / for file
  2130 000050B5 E8A6000000          <1> 	call 	alloc
  2131                              <1> 		; jsr r0,alloc / allocate a new block
  2132                              <1>          ; eAX (r1) = Physical block number
  2133 000050BA 668983[5E6C0000]    <1> 	mov 	[ebx+i.dskp], ax
  2134                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2135 000050C1 E835020000          <1> 	call 	setimod	
  2136                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2137 000050C6 E8C2FEFFFF          <1> 	call	clear
  2138                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2139                              <1> mget_1: ; 2:
  2140                              <1>         ; eAX (r1) = Physical block number
  2141 000050CB C3                  <1> 	retn 
  2142                              <1> 		; rts r0
  2143                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2144 000050CC E88F000000          <1> 	call 	alloc
  2145                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2146                              <1> 	                     ; / block number in r1
  2147                              <1>         ; eAX (r1) = Physical block number
  2148 000050D1 E8CA0C0000          <1> 	call 	wslot
  2149                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2150                              <1> 			     ; / first data word in buffer
  2151                              <1>         ; 03/02/2022
  2152 000050D6 31C9                <1> 	xor	ecx, ecx
  2153 000050D8 B108                <1> 	mov	cl, 8
  2154                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2155                              <1> 		   ; into new indirect block area for the new
  2156                              <1> 		   ; large file		
  2157 000050DA 89DF                <1> 	mov 	edi, ebx ; r5
  2158 000050DC BE[5E6C0000]        <1> 	mov 	esi, i.dskp 
  2159                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2160                              <1> 			   ; / block pointers
  2161                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2162                              <1> 			  ; / large file
  2163                              <1> 	; 22/04/2022
  2164 000050E1 50                  <1> 	push	eax ; * ; bugfix
  2165                              <1> 
  2166                              <1> 	;xor 	ax, ax ; mov ax, 0
  2167                              <1> 	; 03/02/2022
  2168 000050E2 31C0                <1> 	xor	eax, eax
  2169                              <1> mget_3: ;1:
  2170 000050E4 66A5                <1> 	movsw
  2171                              <1> 		; mov (r2),(r5)+
  2172 000050E6 668946FE            <1> 	mov 	[esi-2], ax
  2173                              <1> 		; clr (r2)+
  2174 000050EA E2F8                <1> 	loop	mget_3 ; 1b
  2175                              <1> 		; dec r3
  2176                              <1> 		; bgt 1b
  2177                              <1> 
  2178 000050EC B1F8                <1> 	mov 	cl, 256-8
  2179                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2180                              <1> mget_4:	; 1
  2181 000050EE F366AB              <1> 	rep 	stosw
  2182                              <1> 		; clr (r5)+
  2183                              <1> 		; dec r3
  2184                              <1> 		; bgt 1b
  2185                              <1> 	
  2186                              <1> 	; 22/04/2022
  2187                              <1> 	;pop	eax ; * ; bugfix
  2188                              <1> 
  2189                              <1> 	; 24/03/2013
  2190                              <1>         ; AX (r1) = Physical block number
  2191 000050F1 E8C60C0000          <1> 	call	dskwr
  2192                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2193                              <1> 
  2194                              <1> 	; 22/04/2022
  2195 000050F6 58                  <1> 	pop	eax ; * ; bugfix
  2196                              <1> 
  2197                              <1>         ; eAX (r1) = Physical block number
  2198 000050F7 66A3[5E6C0000]      <1> 	mov 	[i.dskp], ax
  2199                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2200                              <1> 	; 03/02/2022
  2201 000050FD 800D[596C0000]10    <1> 	or	byte [i.flgs+1], 10h
  2202                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2203                              <1> 		; bis $10000,i.flgs / set large file bit 
  2204                              <1> 				  ; / in i.flgs word of i-node
  2205 00005104 E8F2010000          <1> 	call	setimod
  2206                              <1> 		; jsr r0,setimod / set i-node modified flag
  2207 00005109 E97AFFFFFF          <1>         jmp     mget_0 
  2208                              <1> 		; br mget
  2209                              <1> 
  2210                              <1> mget_5:  ; 4 ; large file
  2211                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2212                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2213                              <1> 			    ; / in indirect block
  2214                              <1> 		; mov r2,-(sp) / save on stack (*)
  2215                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2216                              <1>        		          ; / indirect block
  2217                              <1> 		; bic $!16,r2
  2218 0000510E 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2219 00005111 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2220                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2221                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2222                              <1> 	; There is always 1 indirect block for this file system
  2223                              <1> 	; 03/02/2022
  2224 00005112 66A1[5E6C0000]      <1> 	mov	ax, [i.dskp]
  2225                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2226                              <1> 		; mov i.dskp(r2),r1
  2227                              <1> 	; 03/02/2022
  2228 00005118 09C0                <1> 	or	eax, eax
  2229                              <1> 	;or 	ax, ax ; R1
  2230 0000511A 7515                <1> 	jnz 	short mget_6 ; 2f
  2231                              <1> 		; bne 2f / if no indirect block exists
  2232 0000511C E83F000000          <1> 	call 	alloc
  2233                              <1> 		; jsr r0,alloc / allocate a new block
  2234 00005121 66A3[5E6C0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2235                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2236 00005127 E8CF010000          <1> 	call 	setimod
  2237                              <1> 		; jsr r0,setimod / set i-node modified byte
  2238                              <1> 	; eAX = new block number
  2239 0000512C E85CFEFFFF          <1> 	call 	clear
  2240                              <1> 		; jsr r0,clear / clear new block
  2241                              <1> mget_6: ;2
  2242                              <1> 	; 05/03/2013
  2243                              <1> 	; eAX = r1, physical block number (of indirect block)
  2244 00005131 E8F80B0000          <1> 	call 	dskrd ; read indirect block
  2245                              <1> 		; jsr r0,dskrd / read in indirect block
  2246 00005136 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2247                              <1> 		; mov (sp)+,r2 / get offset
  2248                              <1> 	; eAX = r1, physical block number (of indirect block)
  2249 00005137 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2250                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2251                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2252 00005138 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2253                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2254                              <1> 	                  ; / points to location of inter
  2255                              <1> 	; 03/02/2022
  2256 0000513A 668B03              <1> 	mov	ax, [ebx]
  2257                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2258                              <1> 			      ; in file sought in R1 (AX)
  2259                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2260                              <1> 	               	    ; / sought in r1
  2261                              <1> 	; 03/02/2022
  2262 0000513D 09C0                <1> 	or	eax, eax
  2263                              <1> 	;or 	ax, ax
  2264 0000513F 751D                <1>         jnz 	short mget_7 ; 2f
  2265                              <1> 		; bne 2f / if no block exists 
  2266 00005141 E81A000000          <1> 	call 	alloc
  2267                              <1> 		; jsr r0,alloc / allocate a new block
  2268 00005146 668903              <1> 	mov 	[ebx], ax ; R1
  2269                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2270                              <1> 	                    ; / indirect block
  2271 00005149 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2272                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2273 0000514A 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2274 0000514B 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2275 0000514C 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2276                              <1> 		; mov (r2),-(sp) / save block number of new block
  2277                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2278 0000514E E84D0C0000          <1> 	call 	wslot
  2279                              <1> 		; jsr r0,wslot
  2280                              <1>         ; eAX (r1) = physical block number
  2281                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2282 00005153 E8640C0000          <1> 	call 	dskwr
  2283                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2284                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2285                              <1> 			     ; / back out on disk
  2286 00005158 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2287                              <1> 		; mov (sp),r1 / restore block number of new block	
  2288                              <1> 	; eAX (r1) = physical block number of new block
  2289 00005159 E82FFEFFFF          <1> 	call 	clear
  2290                              <1> 		; jsr r0,clear / clear new block	
  2291                              <1> mget_7: ; 2
  2292 0000515E 5A                  <1> 	pop 	edx ; **
  2293                              <1> 		; tst (sp)+ / bump stack pointer
  2294                              <1> 	; eAX (r1) = Block number of new block
  2295 0000515F C3                  <1> 	retn
  2296                              <1> 		; rts r0
  2297                              <1> 
  2298                              <1> alloc:
  2299                              <1> 	; 03/02/2022
  2300                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2301                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2302                              <1> 	;
  2303                              <1> 	; get a free block and 
  2304                              <1> 	; set the corresponding bit in the free storage map
  2305                              <1> 	; 
  2306                              <1> 	; INPUTS ->
  2307                              <1> 	;    cdev (current device)
  2308                              <1> 	;    r2 
  2309                              <1> 	;    r3
  2310                              <1> 	; OUTPUTS ->
  2311                              <1> 	;    r1 (physical block number of block assigned)
  2312                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2313                              <1> 	;
  2314                              <1> 	; ((AX = R1)) output
  2315                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2316                              <1>         ;    ((Modified registers: DX, CX))  
  2317                              <1> 
  2318                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2319                              <1> 		;mov r3,-(sp)
  2320                              <1> 	;push 	ecx
  2321 00005160 53                  <1> 	push 	ebx ; R2
  2322                              <1> 	;push 	edx ; R3
  2323 00005161 BB[147C0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2324                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2325 00005166 803D[406F0000]00    <1> 	cmp 	byte [cdev], 0
  2326                              <1> 		; tst cdev
  2327 0000516D 7605                <1> 	jna	short alloc_1
  2328                              <1> 		; beq 1f / drum is device
  2329 0000516F BB[1C7E0000]        <1> 	mov	ebx, mount
  2330                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2331                              <1> 			      ; / free storage map
  2332                              <1> alloc_1: ; 1
  2333                              <1> 	; 03/02/2022
  2334                              <1> 	;sub	ecx, ecx
  2335                              <1> 	;sub	edx, edx
  2336                              <1> 	;sub	eax, eax
  2337                              <1> 
  2338 00005174 668B0B              <1>         mov	cx, [ebx]
  2339                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2340                              <1> 			     ; / storage map
  2341                              <1> 	; 03/02/2022
  2342 00005177 C1E103              <1> 	shl	ecx, 3
  2343                              <1> 	;shl	cx, 3
  2344                              <1> 		; asl r1 / multiply r1 by eight gives 
  2345                              <1> 		; number of blocks in device
  2346                              <1> 		; asl r1
  2347                              <1> 		; asl r1
  2348                              <1> 	;;push	cx ;; 01/08/2013
  2349                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2350 0000517A 31C0                <1> 	xor 	eax, eax ; 0
  2351                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2352                              <1> alloc_2: ; 1
  2353 0000517C 43                  <1> 	inc 	ebx ; 18/8/2012
  2354 0000517D 43                  <1> 	inc 	ebx ; 
  2355 0000517E 668B13              <1> 	mov 	dx, [ebx]
  2356                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2357                              <1> 	; 03/02/2022
  2358 00005181 09D2                <1> 	or	edx, edx
  2359                              <1> 	;or 	dx, dx
  2360 00005183 750D                <1> 	jnz 	short alloc_3 ; 1f
  2361                              <1> 		; bne 1f / branch if any free blocks in this word	
  2362 00005185 6683C010            <1> 	add 	ax, 16
  2363                              <1> 		; add $16.,r1
  2364                              <1> 	; 03/02/2022
  2365 00005189 39C8                <1> 	cmp	eax, ecx
  2366                              <1> 	;cmp 	ax, cx    
  2367                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2368 0000518B 72EF                <1> 	jb 	short alloc_2
  2369                              <1> 		; blo 1b
  2370                              <1> 	; 14/11/2015
  2371                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2372                              <1> 	;	because of a (DMA or another) r/w error, 
  2373                              <1> 	;	we will be here, at 'jmp panic' code address,
  2374                              <1> 	;	even if the (disk) file system space is not full !!!
  2375                              <1> 	;	(cx = 0)	
  2376                              <1> 	;
  2377 0000518D E908E2FFFF          <1> 	jmp     panic 
  2378                              <1> 		; jmp panic / found no free storage
  2379                              <1> alloc_3: ; 1
  2380                              <1> 	; 03/02/2022
  2381 00005192 D1EA                <1> 	shr	edx, 1
  2382                              <1> 	;shr	dx, 1
  2383                              <1> 		; asr r3 / find a free block
  2384 00005194 7203                <1> 	jc	short alloc_4 ; 1f
  2385                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2386                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2387                              <1> 	; 03/02/2022
  2388 00005196 40                  <1> 	inc	eax
  2389                              <1> 	;inc	ax
  2390                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2391 00005197 EBF9                <1> 	jmp 	short alloc_3
  2392                              <1> 		; br 1b
  2393                              <1> alloc_4: ; 1:
  2394                              <1> 	;; pop cx ;; 01/08/2013
  2395                              <1> 		; tst (sp)+ / bump sp
  2396                              <1> 	; 02/04/2013 
  2397 00005199 E829000000          <1> 	call	free3
  2398                              <1> 		; jsr r0,3f / have found a free block
  2399                              <1> 	; 21/8/2012
  2400 0000519E 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2401 000051A1 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2402                              <1> 		; bic r3,(r2) / set bit for this block 
  2403                              <1> 		            ; / i.e. assign block
  2404                              <1> 		; br 2f
  2405 000051A4 EB09                <1> 	jmp 	short alloc_5
  2406                              <1> 
  2407                              <1> free:
  2408                              <1> 	; 03/02/2022
  2409                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2410                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2411                              <1> 	;
  2412                              <1> 	; calculates byte address and bit position for given block number
  2413                              <1> 	; then sets the corresponding bit in the free storage map
  2414                              <1> 	; 
  2415                              <1> 	; INPUTS ->
  2416                              <1> 	;    r1 - block number for a block structured device
  2417                              <1> 	;    cdev - current device 
  2418                              <1> 	; OUTPUTS ->
  2419                              <1> 	;    free storage map is updated
  2420                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2421                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2422                              <1> 	;
  2423                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2424                              <1>         ;  ((Modified registers: DX, CX))  
  2425                              <1> 
  2426                              <1> 		;mov r2,-(sp) / save r2, r3
  2427                              <1> 		;mov r3,-(sp)
  2428                              <1> 	;push 	ecx
  2429 000051A6 53                  <1> 	push 	ebx ; R2
  2430                              <1> 	;push 	edx ; R3 
  2431                              <1> 
  2432 000051A7 E81B000000          <1>         call    free3
  2433                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2434                              <1> 				 ; / in free storage map for block
  2435 000051AC 660913              <1> 	or 	[ebx], dx  
  2436                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2437                              <1> 			    ;  / indicates free block	
  2438                              <1> 	; 0 -> allocated, 1 -> free
  2439                              <1> 
  2440                              <1> alloc_5:
  2441                              <1> 	; 07/04/2013
  2442                              <1> free_1: ; 2:
  2443                              <1> 	;pop 	edx
  2444                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2445 000051AF 5B                  <1> 	pop	ebx
  2446                              <1> 		; mov (sp)+,r2
  2447                              <1> 	; pop	ecx
  2448 000051B0 803D[406F0000]00    <1> 	cmp 	byte [cdev], 0
  2449                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2450                              <1> 			 ; / cdev = 1, mountable device
  2451 000051B7 7707                <1> 	ja	short alloc_6 ; 1f
  2452                              <1> 		; bne 1f
  2453                              <1> 	;mov	byte [smod], 1
  2454 000051B9 FE05[516F0000]      <1> 	inc 	byte [smod]
  2455                              <1> 		; incb smod / set super block modified for drum
  2456                              <1> 	; eAX (r1) = block number
  2457 000051BF C3                  <1> 	retn
  2458                              <1> 		; rts r0
  2459                              <1> free_2:
  2460                              <1> alloc_6: ; 1:
  2461                              <1> 	;mov 	byte [mmod], 1
  2462 000051C0 FE05[526F0000]      <1> 	inc 	byte [mmod]
  2463                              <1> 		; incb	mmod 
  2464                              <1> 		  ; / set super block modified for mountable device
  2465                              <1> 	; eAX (r1) = block number
  2466 000051C6 C3                  <1> 	retn	
  2467                              <1> 		; rts r0
  2468                              <1> free3:
  2469                              <1> 	; 03/02/2022
  2470                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2471                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2472                              <1> 	;
  2473                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2474                              <1> 	; 
  2475                              <1> alloc_free_3: ; 3
  2476                              <1> 	;mov 	dx, 1
  2477                              <1> 	; 03/02/2022
  2478 000051C7 31D2                <1> 	xor	edx, edx
  2479 000051C9 42                  <1> 	inc	edx
  2480                              <1> 	; edx = 1
  2481 000051CA 88C1                <1> 	mov 	cl, al
  2482                              <1> 		; mov r1,r2 / block number, k, = 1		
  2483 000051CC 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2484                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2485 000051CF 7402                <1> 	jz 	short free4
  2486                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2487                              <1> 			       ; / (k) mod 8
  2488                              <1> 	;shl 	dx, cl
  2489                              <1> 	; 03/02/2022
  2490 000051D1 D3E2                <1> 	shl	edx, cl
  2491                              <1> free4:
  2492 000051D3 0FB7D8              <1> 	movzx 	ebx, ax
  2493                              <1> 		; mov r1,r2 / divide block number by 16
  2494                              <1> 	; 03/02/2022
  2495 000051D6 C1EB04              <1> 	shr	ebx, 4
  2496                              <1> 	;shr 	bx, 4
  2497                              <1> 		; asr r2
  2498                              <1> 		; asr r2
  2499                              <1> 		; asr r2
  2500                              <1> 		; asr r2
  2501                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2502                              <1> 		       ; / bit for block is in lower half of word
  2503                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2504                              <1> 		        ; / storage map
  2505                              <1> alloc_free_4: ; 1
  2506                              <1> 	; 03/02/2022
  2507 000051D9 D1E3                <1> 	shl	ebx, 1
  2508                              <1> 	;shl 	bx, 1
  2509                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2510 000051DB 81C3[167C0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2511                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2512                              <1> 	    		        ; / with block bit in it 	
  2513 000051E1 803D[406F0000]00    <1> 	cmp	byte [cdev], 0
  2514                              <1> 		; tst cdev
  2515 000051E8 7606                <1> 	jna	short alloc_free_5
  2516                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2517 000051EA 81C308020000        <1> 	add	ebx, mount - systm
  2518                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2519                              <1> 				    ; / mountable device with bit of block to be
  2520                              <1> 				    ; / freed
  2521                              <1> alloc_free_5: ; 1 
  2522 000051F0 C3                  <1> 	retn
  2523                              <1> 		; rts r0 / return to 'free'
  2524                              <1> 	      ; 2
  2525                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2526                              <1> 	
  2527                              <1> iget:
  2528                              <1> 	; 03/02/2022
  2529                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2530                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2531                              <1> 	;
  2532                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2533                              <1> 	;
  2534                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2535                              <1> 	; 
  2536                              <1> 	; INPUTS ->
  2537                              <1> 	;    ii - current i-number, rootdir
  2538                              <1> 	;    cdev - new i-node device
  2539                              <1> 	;    idev - current i-node device
  2540                              <1> 	;    imod - current i-node modified flag
  2541                              <1> 	;    mnti - cross device file i-number
  2542                              <1> 	;    r1 - i-numbe rof new i-node
  2543                              <1> 	;    mntd - mountable device number		
  2544                              <1> 	; 	 
  2545                              <1> 	; OUTPUTS ->
  2546                              <1> 	;    cdev, idev, imod, ii, r1
  2547                              <1> 	;
  2548                              <1> 	; ((AX = R1)) input/output
  2549                              <1> 	;
  2550                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2551                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2552                              <1> 
  2553 000051F1 8A15[406F0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2554 000051F7 8A35[3E6F0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2555                              <1> 	;
  2556 000051FD 663B05[3C6F0000]    <1> 	cmp 	ax, [ii]
  2557                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2558 00005204 7504                <1> 	jne 	short iget_1
  2559                              <1> 		; bne 1f
  2560 00005206 38F2                <1> 	cmp	dl, dh
  2561                              <1> 		; cmp idev,cdev
  2562                              <1> 			  ; / is device number of i-node = current device
  2563 00005208 7472                <1>         je      short iget_5
  2564                              <1> 		; beq 2f
  2565                              <1> iget_1: ; 1:
  2566 0000520A 30DB                <1> 	xor	bl, bl
  2567 0000520C 381D[506F0000]      <1> 	cmp	[imod], bl ; 0	
  2568                              <1> 		; tstb imod / has i-node of current file
  2569                              <1> 			  ; / been modified i.e., imod set
  2570 00005212 7629                <1> 	jna	short iget_2
  2571                              <1> 		; beq 1f
  2572 00005214 881D[506F0000]      <1> 	mov	[imod], bl ; 0
  2573                              <1> 		;  clrb	imod / if it has, 
  2574                              <1> 			   ; / we must write the new i-node out on disk
  2575                              <1> 	; 03/02/2022
  2576 0000521A 50                  <1> 	push	eax ; *
  2577                              <1> 	;push	ax
  2578                              <1> 		; mov r1,-(sp)
  2579                              <1> 	;mov	dl, [cdev]
  2580 0000521B 52                  <1> 	push	edx ; **
  2581                              <1> 	;push	dx
  2582                              <1> 		; mov cdev,-(sp)
  2583 0000521C 66A1[3C6F0000]      <1> 	mov	ax, [ii]
  2584                              <1> 		; mov ii,r1
  2585                              <1> 	;mov	dh, [idev]
  2586 00005222 8835[406F0000]      <1> 	mov	[cdev], dh
  2587                              <1> 		; mov idev,cdev
  2588 00005228 FEC3                <1> 	inc	bl ; 1
  2589                              <1> 	; 31/07/2013
  2590 0000522A 881D[D86F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2591                              <1> 	;;28/07/2013 rw -> u.rw
  2592                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2593 00005230 E848000000          <1> 	call	icalc
  2594                              <1> 		; jsr r0,icalc; 1
  2595                              <1> 	;pop	dx
  2596                              <1> 	; 03/02/2022
  2597 00005235 5A                  <1> 	pop	edx ; **
  2598 00005236 8815[406F0000]      <1> 	mov	[cdev], dl
  2599                              <1> 		; mov (sp)+,cdev
  2600                              <1> 	; 03/02/2022
  2601 0000523C 58                  <1> 	pop	eax ; *
  2602                              <1> 	;pop	ax
  2603                              <1> 		; mov (sp)+,r1
  2604                              <1> iget_2: ; 1:
  2605 0000523D 6621C0              <1> 	and	ax, ax
  2606                              <1> 		; tst r1 / is new i-number non zero
  2607 00005240 7434                <1> 	jz	short iget_4 ; 2f
  2608                              <1> 		; beq 2f / branch if r1=0
  2609                              <1> 
  2610                              <1> 	;mov 	dl, [cdev]
  2611 00005242 08D2                <1> 	or	dl, dl
  2612                              <1> 		; tst cdev / is the current device number non zero
  2613                              <1> 			 ; / (i.e., device =/ drum)
  2614 00005244 7517                <1> 	jnz	short iget_3 ;  1f
  2615                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2616 00005246 663B05[466F0000]    <1> 	cmp	ax, [mnti]			
  2617                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2618                              <1> 			    ; / file (root directory of mounted device)
  2619 0000524D 750E                <1> 	jne	short iget_3 ; 1f
  2620                              <1> 		; bne 1f
  2621                              <1>         ;mov    bl, [mntd]
  2622 0000524F FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2623 00005251 8815[406F0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2624                              <1> 		; mov mntd,cdev / make mounted device the current device
  2625 00005257 66A1[4C6F0000]      <1> 	mov	ax, [rootdir]
  2626                              <1> 		; mov rootdir,r1
  2627                              <1> iget_3: ; 1:
  2628 0000525D 66A3[3C6F0000]      <1> 	mov	[ii], ax
  2629                              <1> 		; mov r1,ii
  2630 00005263 8815[3E6F0000]      <1> 	mov	[idev], dl ; cdev
  2631                              <1> 		; mov cdev,idev
  2632 00005269 30DB                <1> 	xor	bl, bl
  2633                              <1>         ; 31/07/2013
  2634 0000526B 881D[D86F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2635                              <1> 	;;28/07/2013 rw -> u.rw       
  2636                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2637 00005271 E807000000          <1> 	call	icalc
  2638                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2639                              <1> iget_4: ; 2:
  2640 00005276 66A1[3C6F0000]      <1> 	mov	ax, [ii]
  2641                              <1> 		; mov ii,r1
  2642                              <1> iget_5:
  2643 0000527C C3                  <1> 	retn
  2644                              <1> 		; rts r0
  2645                              <1> 
  2646                              <1> icalc:
  2647                              <1> 	; 04/04/2022 (47->31)
  2648                              <1> 	;	(Inode Table/List Address modification)
  2649                              <1> 	; 03/02/2022
  2650                              <1> 	; 02/07/2015
  2651                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2652                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2653                              <1> 	;
  2654                              <1> 	; calculate physical block number from i-number then
  2655                              <1> 	; read or write that block
  2656                              <1> 	;
  2657                              <1> 	; 'icalc' is called from 'iget'
  2658                              <1> 	;
  2659                              <1> 	; for original unix v1:
  2660                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2661                              <1>        	; / (i+31.) mod 16. bytes from its start
  2662                              <1> 	;
  2663                              <1> 	; for retro unix 8086 v1:
  2664                              <1> 	;  i-node is located in block (i+47)/16 and
  2665                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2666                              <1> 	;
  2667                              <1> 	; INPUTS ->
  2668                              <1> 	;    r1 - i-number of i-node
  2669                              <1> 	; 	 
  2670                              <1> 	; OUTPUTS ->
  2671                              <1> 	;    inode r/w
  2672                              <1> 	;
  2673                              <1> 	; ((AX = R1)) input
  2674                              <1> 	;
  2675                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2676                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2677                              <1> 	;
  2678 0000527D 0FB7D0              <1> 	movzx	edx, ax	
  2679                              <1> 	;add	dx, 47
  2680                              <1> 	; 04/04/2022
  2681 00005280 6683C21F            <1> 	add	dx, 31
  2682 00005284 89D0                <1> 	mov	eax, edx
  2683                              <1> 	;;add	ax, 47	; add 47 to inode number
  2684                              <1> 	;add	ax, 31
  2685                              <1> 		; add $31.,r1 / add 31. to i-number
  2686 00005286 50                  <1> 	push	eax
  2687                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2688                              <1> 	; 03/02/2022
  2689 00005287 C1E804              <1> 	shr	eax, 4
  2690                              <1> 	;shr 	ax, 4
  2691                              <1> 		; asr r1 / divide by 16.
  2692                              <1> 		; asr r1
  2693                              <1> 		; asr r1
  2694                              <1> 		; asr r1 / r1 contains block number of block
  2695                              <1> 		       ; / in which i-node exists
  2696 0000528A E89F0A0000          <1> 	call	dskrd
  2697                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2698                              <1> 	; 31/07/2013
  2699 0000528F 803D[D86F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2700                              <1> 	;; 28/07/2013 rw -> u.rw
  2701                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2702                              <1> 		; tst (r0)
  2703 00005296 7605                <1> 	jna	short icalc_1
  2704                              <1> 		; beq 1f / branch to wslot when argument
  2705                              <1> 		       ; / in icalc call = 1
  2706                              <1> 	; eAX = r1 = block number
  2707 00005298 E8030B0000          <1> 	call	wslot
  2708                              <1> 		; jsr r0,wslot / set up data buffer for write
  2709                              <1> 			     ; / (will be same buffer as dskrd got)
  2710                              <1> 	; eBX = r5 points to first word in data area for this block
  2711                              <1> icalc_1: ; 1:
  2712 0000529D 5A                  <1> 	pop	edx 
  2713 0000529E 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2714                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2715                              <1> 			      ; / gives (i+31.) mod 16
  2716 000052A1 C1E205              <1> 	shl 	edx, 5
  2717                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2718 000052A4 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2719 000052A6 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2720                              <1>           	; eSI (r5) points to first word in i-node i.	
  2721                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2722                              <1> 			     ; / 32.*(i+31.)mod16
  2723                              <1> 		; mov $5,lsh / for i-node i.
  2724                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2725 000052A8 BF[586C0000]        <1> 	mov	edi, inode
  2726                              <1> 		; mov $inode,r1 / inode is address of first word 
  2727                              <1> 			      ; / of current i-node
  2728                              <1> 	; 03/02/2022
  2729 000052AD 29C9                <1> 	sub	ecx, ecx
  2730 000052AF B108                <1> 	mov	cl, 8 
  2731                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2732                              <1> 		; mov $16.,r3
  2733                              <1>         ; 31/07/2013
  2734 000052B1 382D[D86F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2735                              <1>        ;;28/07/2013 rw -> u.rw                 
  2736                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2737                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2738 000052B7 7609                <1> 	jna	short icalc_3
  2739                              <1> 		; beq 2f / r0 now contains proper return address 
  2740                              <1> 		       ; / for rts r0
  2741                              <1> icalc_2: ; 1:
  2742 000052B9 87F7                <1> 	xchg 	esi, edi
  2743                              <1> 	; overwrite old i-node (in buffer to be written)
  2744 000052BB F3A5                <1> 	rep 	movsd
  2745                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2746                              <1> 		; dec r3
  2747                              <1> 		; bgt 1b
  2748                              <1> 	;call	dskwr
  2749                              <1> 		; jsr r0,dskwr / write inode out on device
  2750                              <1> 	;retn
  2751                              <1> 		; rts r0
  2752                              <1> 	; 03/02/2022
  2753 000052BD E9FA0A0000          <1> 	jmp	dskwr
  2754                              <1> icalc_3: ; 2:
  2755                              <1> 	; copy new i-node into inode area of (core) memory
  2756 000052C2 F3A5                <1> 	rep 	movsd
  2757                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2758                              <1> 		                ; / "inode" area of core
  2759                              <1> 		; dec r3
  2760                              <1> 		; bgt 2b
  2761 000052C4 C3                  <1> 	retn
  2762                              <1> 		; rts r0
  2763                              <1> 
  2764                              <1> access:
  2765                              <1> 	; 03/02/2022
  2766                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2767                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2768                              <1> 	;
  2769                              <1> 	; check whether user is owner of file or user has read or write
  2770                              <1> 	; permission (based on i.flgs).
  2771                              <1> 	;
  2772                              <1> 	; INPUTS ->
  2773                              <1> 	;    r1 - i-number of file
  2774                              <1> 	;    u.uid
  2775                              <1> 	; arg0 -> (owner flag mask)	 		
  2776                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2777                              <1> 	; OUTPUTS ->
  2778                              <1> 	;    inode (or jump to error)
  2779                              <1> 	;
  2780                              <1> 	; ((AX = R1)) input/output
  2781                              <1> 	;
  2782                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2783                              <1> 	;
  2784                              <1> 
  2785                              <1> 	;push	dx  ; save flags (DL)
  2786                              <1> 	; 03/02/2022
  2787 000052C5 52                  <1> 	push	edx ; save flags (DL)
  2788 000052C6 E826FFFFFF          <1> 	call	iget
  2789                              <1> 		; jsr r0,iget / read in i-node for current directory
  2790                              <1> 			    ; / (i-number passed in r1)
  2791 000052CB 8A0D[586C0000]      <1> 	mov	cl, [i.flgs]
  2792                              <1> 		; mov i.flgs,r2
  2793                              <1> 	; 03/02/2022
  2794 000052D1 5A                  <1> 	pop	edx ; restore flags (DL)
  2795                              <1> 	;pop	dx  ; restore flags (DL)
  2796 000052D2 8A35[A26F0000]      <1> 	mov	dh, [u.uid]
  2797 000052D8 3A35[5B6C0000]      <1> 	cmp	dh, [i.uid]
  2798                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2799 000052DE 7503                <1> 	jne	short access_1
  2800                              <1> 		; bne 1f / no, then branch
  2801 000052E0 C0E902              <1> 	shr	cl, 2
  2802                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2803                              <1> 		        ; / read/write bits
  2804                              <1> 		; asrb r2
  2805                              <1> access_1: ; 1:
  2806 000052E3 20D1                <1> 	and	cl, dl
  2807                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2808                              <1> 			     ; / in access call
  2809 000052E5 7513                <1> 	jnz	short access_2
  2810                              <1> 		; bne 1f
  2811 000052E7 08F6                <1> 	or	dh, dh	; super user  (root) ?
  2812                              <1> 		; tstb u.uid
  2813 000052E9 740F                <1> 	jz	short access_2 ; yes, super user
  2814                              <1> 	;jnz	error
  2815                              <1> 		; beq 1f
  2816                              <1> 		; jmp error
  2817 000052EB C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2817 000052F3 0000                <1>
  2818                              <1> 			; 'permission denied !' error
  2819 000052F5 E9E1E7FFFF          <1> 	jmp	error
  2820                              <1> 
  2821                              <1> access_2: ; 1:
  2822                              <1> 	; DL = flags
  2823 000052FA C3                  <1> 	retn
  2824                              <1> 		; rts r0
  2825                              <1> 
  2826                              <1> setimod:
  2827                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2828                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2829                              <1> 	;
  2830                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2831                              <1> 	; the inode has been modified. Also puts the time of modification
  2832                              <1> 	; into the inode.
  2833                              <1> 	;
  2834                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2835                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  2836                              <1> 	;
  2837                              <1> 	
  2838                              <1> 	; push 	edx
  2839 000052FB 50                  <1> 	push	eax
  2840                              <1> 
  2841 000052FC C605[506F0000]01    <1> 	mov 	byte [imod], 1
  2842                              <1> 		; movb $1,imod / set current i-node modified bytes
  2843                              <1> 	; Erdogan Tan 14-7-2012
  2844 00005303 E821E3FFFF          <1> 	call 	epoch
  2845                              <1> 		 ; mov s.time,i.mtim 
  2846                              <1> 			    ; / put present time into file modified time
  2847                              <1> 		 ; mov s.time+2,i.mtim+2
  2848                              <1> 
  2849 00005308 A3[726C0000]        <1> 	mov 	[i.mtim], eax
  2850                              <1> 	
  2851                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2852                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2853 0000530D 833D[6E6C0000]00    <1> 	cmp	dword [i.ctim], 0
  2854 00005314 7505                <1> 	jnz	short setimod_ok
  2855                              <1> 
  2856 00005316 A3[6E6C0000]        <1> 	mov 	[i.ctim], eax
  2857                              <1> 
  2858                              <1> setimod_ok: ; 31/07/2013
  2859 0000531B 58                  <1> 	pop	eax
  2860                              <1> 	;pop	edx
  2861                              <1> 	
  2862 0000531C C3                  <1> 	retn
  2863                              <1> 		; rts r0
  2864                              <1> 
  2865                              <1> itrunc:
  2866                              <1> 	; 03/02/2022
  2867                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2868                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2869                              <1> 	;
  2870                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2871                              <1> 	;  to zero length.
  2872                              <1> 	;
  2873                              <1> 	; INPUTS ->
  2874                              <1> 	;    r1 - i-number of i-node
  2875                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2876                              <1> 	;    i.flgs - large file flag		
  2877                              <1> 	;    i.size - size of file	
  2878                              <1> 	; 	 
  2879                              <1> 	; OUTPUTS ->
  2880                              <1> 	;    i.flgs - large file flag is cleared
  2881                              <1> 	;    i.size - set to 0	
  2882                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2883                              <1> 	;    setimod - set to indicate i-node has been modified
  2884                              <1> 	;    r1 - i-number of i-node  					
  2885                              <1> 	;
  2886                              <1> 	; ((AX = R1)) input/output
  2887                              <1> 	;
  2888                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2889                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2890                              <1> 
  2891 0000531D E8CFFEFFFF          <1> 	call	iget
  2892                              <1> 		; jsr r0,iget
  2893 00005322 BE[5E6C0000]        <1> 	mov	esi, i.dskp
  2894                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2895 00005327 31C0                <1> 	xor	eax, eax
  2896                              <1> itrunc_1: ; 1:
  2897 00005329 66AD                <1> 	lodsw
  2898                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2899                              <1> 	; 03/02/2022
  2900 0000532B 09C0                <1> 	or	eax, eax
  2901                              <1> 	;or 	ax, ax
  2902 0000532D 7433                <1> 	jz	short itrunc_5
  2903                              <1> 		; beq 5f
  2904 0000532F 56                  <1> 	push	esi
  2905                              <1> 		; mov r2,-(sp)
  2906                              <1> 	; 03/02/2022
  2907 00005330 F605[596C0000]10    <1> 	test	byte [i.flgs+1], 10h
  2908                              <1> 	;test	word [i.flgs], 1000h
  2909                              <1> 		; bit $10000,i.flgs / test large file bit?
  2910 00005337 7423                <1> 	jz	short itrunc_4
  2911                              <1> 		; beq 4f / if clear, branch
  2912 00005339 50                  <1> 	push	eax
  2913                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2914 0000533A E8EF090000          <1> 	call	dskrd
  2915                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2916                              <1> 			     ; / pointed to by r5
  2917                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2918                              <1> 	; 03/02/2022
  2919 0000533F 31C9                <1> 	xor	ecx, ecx
  2920 00005341 FEC5                <1> 	inc	ch ; mov ch, 1
  2921                              <1> 	; ecx = 256
  2922                              <1> 	;mov	ecx, 256
  2923                              <1> 		; mov $256.,r3 / move word count into r3
  2924 00005343 89DE                <1> 	mov	esi, ebx
  2925                              <1> itrunc_2: ; 2:
  2926 00005345 66AD                <1> 	lodsw
  2927                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2928                              <1> 			     ; / physical block number
  2929                              <1> 	; 03/02/2022
  2930 00005347 21C0                <1> 	and	eax, eax
  2931                              <1> 	;and	ax, ax
  2932 00005349 7407                <1> 	jz	short itrunc_3
  2933                              <1> 		; beq 3f / branch if zero
  2934                              <1> 	; 03/02/2022
  2935 0000534B 51                  <1> 	push	ecx
  2936                              <1> 	;push	cx
  2937                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2938                              <1> 	;push	esi
  2939                              <1> 		; mov r5,-(sp)
  2940 0000534C E855FEFFFF          <1> 	call	free
  2941                              <1> 		; jsr r0,free / free block in free storage map
  2942                              <1> 	;pop	esi
  2943                              <1> 		; mov(sp)+,r5
  2944                              <1> 	;pop	cx
  2945 00005351 59                  <1> 	pop	ecx
  2946                              <1> 		; mov (sp)+,r3
  2947                              <1> itrunc_3: ; 3:
  2948 00005352 E2F1                <1> 	loop	itrunc_2
  2949                              <1> 		; dec r3 / decrement word count
  2950                              <1> 		; bgt 2b / branch if positive
  2951 00005354 58                  <1> 	pop	eax
  2952                              <1> 		; mov (sp)+,r1 / put physical block number of 
  2953                              <1> 			     ; / indirect block
  2954                              <1> 	; 01/08/2013
  2955                              <1>         ;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2956                              <1> 	; 03/02/2022
  2957 00005355 8025[596C0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  2958                              <1> itrunc_4: ; 4:
  2959 0000535C E845FEFFFF          <1> 	call	free
  2960                              <1> 		; jsr r0,free / free indirect block
  2961 00005361 5E                  <1> 	pop	esi
  2962                              <1> 		; mov (sp)+,r2
  2963                              <1> itrunc_5: ; 5:
  2964 00005362 81FE[6E6C0000]      <1> 	cmp	esi, i.dskp+16
  2965                              <1> 		; cmp r2,$i.dskp+16.
  2966 00005368 72BF                <1> 	jb	short itrunc_1	
  2967                              <1> 		; bne 1b / branch until all i.dskp entries check
  2968                              <1> 	; 03/02/2022
  2969                              <1> 	;and	byte [i.flgs+1], 0EFh
  2970                              <1> 	; 01/08/2013
  2971                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  2972                              <1> 		; bic $10000,i.flgs / clear large file bit
  2973 0000536A BF[5E6C0000]        <1> 	mov	edi, i.dskp
  2974                              <1> 	;mov	cx, 8
  2975                              <1> 	;xor 	ax, ax
  2976                              <1> 	; 03/02/2022
  2977 0000536F 29C9                <1> 	sub	ecx, ecx
  2978 00005371 B108                <1> 	mov	cl, 8
  2979 00005373 29C0                <1> 	sub	eax, eax
  2980 00005375 66A3[5C6C0000]      <1> 	mov	[i.size], ax ; 0
  2981                              <1> 		; clr i.size / zero file size
  2982 0000537B F366AB              <1> 	rep	stosw
  2983                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  2984                              <1> 			   ; / zero block pointers
  2985 0000537E E878FFFFFF          <1> 	call	setimod
  2986                              <1> 		; jsr r0,setimod / set i-node modified flag
  2987 00005383 66A1[3C6F0000]      <1> 	mov	ax, [ii]
  2988                              <1> 		; mov ii,r1
  2989 00005389 C3                  <1> 	retn
  2990                              <1> 		; rts r0
  2991                              <1> 
  2992                              <1> imap:
  2993                              <1> 	; 12/02/2022
  2994                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2995                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  2996                              <1> 	;
  2997                              <1> 	; 'imap' finds the byte in core (superblock) containing
  2998                              <1> 	; allocation bit for an i-node whose number in r1.
  2999                              <1> 	;
  3000                              <1> 	; INPUTS ->
  3001                              <1> 	;    r1 - contains an i-number
  3002                              <1> 	;    fsp - start of table containing open files
  3003                              <1> 	;
  3004                              <1> 	; OUTPUTS ->
  3005                              <1> 	;    r2 - byte address of byte with the allocation bit
  3006                              <1> 	;    mq - a mask to locate the bit position.	
  3007                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3008                              <1> 	;
  3009                              <1> 	; ((AX = R1)) input/output
  3010                              <1> 	; ((DL/DX = MQ)) output
  3011                              <1> 	; ((BX = R2)) output
  3012                              <1> 	;
  3013                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3014                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3015                              <1> 	;
  3016                              <1> 		; / get the byte that has the allocation bit for 
  3017                              <1> 		; / the i-number contained in r1
  3018                              <1> 	;mov	dx, 1
  3019 0000538A B201                <1> 	mov	dl, 1
  3020                              <1> 		; mov $1,mq / put 1 in the mq
  3021 0000538C 0FB7D8              <1> 	movzx	ebx, ax
  3022                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3023                              <1>  		          ; / in the map we must find
  3024 0000538F 6683EB29            <1> 	sub	bx, 41
  3025                              <1> 		; sub $41.,r2 / r2 has i-41
  3026 00005393 88D9                <1> 	mov	cl, bl
  3027                              <1> 		; mov r2,r3 / r3 has i-41
  3028 00005395 80E107              <1> 	and	cl, 7
  3029                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3030                              <1> 			   ; / the bit position
  3031 00005398 7402                <1> 	jz	short imap1
  3032                              <1> 	;shl	dx, cl
  3033 0000539A D2E2                <1> 	shl	dl, cl
  3034                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3035                              <1> imap1:			   ; / to the left to mask the correct bit
  3036                              <1> 	; 03/02/2022
  3037 0000539C C1EB03              <1> 	shr	ebx, 3
  3038                              <1> 	;shr	bx, 3
  3039                              <1> 		; asr r2
  3040                              <1> 		; asr r2
  3041                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3042                              <1> 		       ; / from the start of the map
  3043                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3044 0000539F BE[147C0000]        <1> 	mov	esi, systm
  3045                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3046                              <1> 				; / the super block for drum
  3047                              <1> 	;cmp	word [cdev], 0
  3048 000053A4 803D[406F0000]00    <1> 	cmp	byte [cdev], 0
  3049                              <1> 		; tst cdev / is the device the disk
  3050 000053AB 7606                <1> 	jna	short imap2
  3051                              <1> 		; beq 1f / yes
  3052 000053AD 81C608020000        <1> 	add	esi, mount - systm
  3053                              <1> 		; add $mount-systm,r2 / for mounted device,
  3054                              <1> 			; / r2 points to 1st word of its super block
  3055                              <1> imap2: ; 1:
  3056 000053B3 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3057                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3058 000053B6 6683C304            <1> 	add	bx, 4
  3059 000053BA 01F3                <1> 	add	ebx, esi
  3060                              <1>         	; add (sp)+,r2 / ?
  3061                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3062                              <1> 		      ;; (2 + free map size + 2)
  3063                              <1> 		; add $2,r2 / ?
  3064                              <1>  	
  3065                              <1> 	; 12/02/2022
  3066 000053BC 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3067 000053C2 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3068                              <1> 			  ; if inode num overs inode count
  3069                              <1> 
  3070                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3071                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3072                              <1> 
  3073                              <1> 	; 11/02/2022
  3074                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3075                              <1> 	;	(number of requested inode > inode count)
  3076                              <1> 
  3077 000053C4 C3                  <1> 	retn
  3078                              <1> 		; rts r0
  2052                                  %include 'u6.s'        ; 31/05/2015
  2053                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2054                              <1> ; Last Modification: 03/02/2022
  2055                              <1> ; ----------------------------------------------------------------------------
  2056                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2057                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2058                              <1> ;
  2059                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2060                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2061                              <1> ; <Bell Laboratories (17/3/1972)>
  2062                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2063                              <1> ;
  2064                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2065                              <1> ;
  2066                              <1> ; ****************************************************************************
  2067                              <1> ; 18/11/2015
  2068                              <1> 
  2069                              <1> readi:
  2070                              <1> 	; 03/02/2022
  2071                              <1> 	; 20/05/2015
  2072                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2073                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2074                              <1> 	;
  2075                              <1> 	; Reads from an inode whose number in R1
  2076                              <1> 	; 
  2077                              <1> 	; INPUTS ->
  2078                              <1> 	;    r1 - inode number
  2079                              <1> 	;    u.count - byte count user desires
  2080                              <1> 	;    u.base - points to user buffer
  2081                              <1> 	;    u.fofp - points to word with current file offset
  2082                              <1> 	; OUTPUTS ->
  2083                              <1> 	;    u.count - cleared
  2084                              <1> 	;    u.nread - accumulates total bytes passed back
  2085                              <1> 	;
  2086                              <1> 	; ((AX = R1)) input/output
  2087                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2088                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2089                              <1> 
  2090 000053C5 31D2                <1> 	xor	edx, edx ; 0
  2091 000053C7 8915[846F0000]      <1> 	mov 	[u.nread], edx ; 0
  2092                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2093 000053CD 668915[BB6F0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2094 000053D4 3915[806F0000]      <1> 	cmp 	[u.count], edx ; 0
  2095                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2096 000053DA 7701                <1> 	ja 	short readi_1 ; 1f
  2097                              <1> 		 ; bgt 1f / yes, branch
  2098 000053DC C3                  <1> 	retn
  2099                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2100                              <1> readi_1: ; 1:
  2101                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2102 000053DD 6683F828            <1> 	cmp	ax, 40
  2103                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2104                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2105                              <1>         ;ja	dskr 
  2106                              <1> 		 ; ble 1f / yes, branch
  2107                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2108                              <1> 		 ;         / read file with i-node number (r1)
  2109                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2110                              <1> 	; 03/02/2022
  2111 000053E1 7605                <1> 	jna	short readi_3
  2112 000053E3 E9CF000000          <1> 	jmp	dskr
  2113                              <1> readi_3:
  2114                              <1> 	; (20/05/2015)
  2115 000053E8 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2116                              <1> 	; 1:
  2117 000053E9 0FB6D8              <1> 	movzx	ebx, al
  2118                              <1> 	; 03/02/2022
  2119 000053EC C1E302              <1> 	shl	ebx, 2
  2120                              <1> 	;shl	bx, 2
  2121                              <1> 		 ; asl r1 / multiply inode number by 2
  2122 000053EF 81C3[F3530000]      <1> 	add	ebx, readi_2 - 4
  2123 000053F5 FF23                <1> 	jmp	dword [ebx]	
  2124                              <1> 		 ; jmp *1f-2(r1)
  2125                              <1> readi_2: ; 1:
  2126 000053F7 [43540000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2127                              <1> 		 ;rtty / tty; r1=2
  2128                              <1> 		 ;rppt / ppt; r1=4
  2129 000053FB [93540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2130                              <1> 		 ;rmem / mem; r1=6
  2131                              <1> 		 ;rrf0 / rf0
  2132                              <1> 		 ;rrk0 / rk0
  2133                              <1> 		 ;rtap / tap0
  2134                              <1> 		 ;rtap / tap1
  2135                              <1> 		 ;rtap / tap2
  2136                              <1> 		 ;rtap / tap3
  2137                              <1> 		 ;rtap / tap4
  2138                              <1> 		 ;rtap / tap5
  2139                              <1> 		 ;rtap / tap6
  2140                              <1> 		 ;rtap / tap7
  2141 000053FF [DF5B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2142 00005403 [DF5B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2143 00005407 [DF5B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2144 0000540B [DF5B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2145 0000540F [DF5B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2146 00005413 [DF5B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2147 00005417 [A8540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2148 0000541B [8F540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2149                              <1> 		 ;rcvt / tty0
  2150 0000541F [8F540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2151                              <1> 		 ;rcvt / tty1
  2152 00005423 [8F540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2153                              <1> 		 ;rcvt / tty2
  2154 00005427 [8F540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2155                              <1> 		 ;rcvt / tty3
  2156 0000542B [8F540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2157                              <1> 		 ;rcvt / tty4
  2158 0000542F [8F540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2159                              <1> 		 ;rcvt / tty5
  2160 00005433 [8F540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2161                              <1> 		 ;rcvt / tty6
  2162 00005437 [8F540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2163                              <1> 		 ;rcvt / tty7
  2164 0000543B [8F540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2165                              <1> 		 ;rcrd / crd
  2166 0000543F [8F540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2167                              <1> 
  2168                              <1> rtty: ; / read from console tty
  2169                              <1> 	; 03/02/2022
  2170                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2171                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2172                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2173                              <1> 	;	     must be written immediate on video page (screen)
  2174                              <1> 	;	     when it is required.	
  2175                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2176                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2177                              <1> 	;
  2178                              <1> 	; Console tty buffer is PC keyboard buffer
  2179                              <1> 	; and keyboard-keystroke handling is different than original
  2180                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2181                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2182                              <1> 	;
  2183                              <1> 	; 06/12/2013
  2184 00005443 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2185 0000544A 8A83[B76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2186                              <1> rttys:
  2187                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2188                              <1> 	               ; / of the control and status block
  2189                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2190                              <1> 		       ; / tty buffer
  2191                              <1> 	; 28/07/2013
  2192 00005450 A2[AA6F0000]        <1> 	mov 	[u.ttyn], al
  2193                              <1> 	; 13/01/2014
  2194 00005455 FEC0                <1> 	inc	al
  2195 00005457 A2[8C6F0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2196                              <1> rtty_nc: ; 01/02/2014
  2197                              <1> 	; 29/09/2013
  2198                              <1> 	;mov	ecx, 10
  2199                              <1> 	; 03/02/2022
  2200 0000545C 29C9                <1> 	sub	ecx, ecx
  2201 0000545E B10A                <1> 	mov	cl, 10
  2202                              <1> rtty_1: 	; 01/02/2014
  2203                              <1> 	;push 	cx ; 29/09/2013
  2204                              <1> 	; 03/02/2022
  2205 00005460 51                  <1> 	push	ecx
  2206                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2207 00005461 B001                <1> 	mov 	al, 1
  2208 00005463 E8C70B0000          <1> 	call 	getc
  2209                              <1> 	; 03/02/2022
  2210 00005468 59                  <1> 	pop	ecx
  2211                              <1> 	;pop 	cx ; 29/09/2013	
  2212 00005469 7516                <1> 	jnz	short rtty_2
  2213                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2214                              <1> 	               ; / of chars. Is this number non-zero?
  2215 0000546B E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2216                              <1> 	; 05/10/2013
  2217 0000546D 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn]
  2218                              <1> 	; 29/09/2013
  2219 00005473 E898FBFFFF          <1> 	call	sleep
  2220                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2221                              <1>                 ;           / (120 chars.)
  2222                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2223 00005478 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2224                              <1> 
  2225                              <1> rtty_idle:
  2226                              <1> 	; 29/07/2013
  2227 0000547A E804FBFFFF          <1> 	call 	idle
  2228 0000547F EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2229                              <1> 	;1:
  2230                              <1> 		; tst 2(r5) / is the number of characters zero
  2231                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2232                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2233                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2234                              <1> 		          ; / contains the next char.
  2235                              <1> 		; dec 2(r5) / decrement the character count
  2236                              <1> rtty_2:
  2237 00005481 30C0                <1> 	xor 	al, al
  2238 00005483 E8A70B0000          <1> 	call 	getc
  2239 00005488 E892000000          <1> 	call	passc
  2240                              <1> 		; jsr r0,passc / move the character to core (user)
  2241                              <1> 	;; 17/10/2015 - 16/07/2015
  2242                              <1> 	; 19/06/2014
  2243                              <1> 	;;jnz	short rtty_nc
  2244 0000548D 58                  <1> 	pop	eax  ; (20/05/2015)
  2245 0000548E C3                  <1> 	retn 
  2246                              <1> ;ret1:
  2247                              <1> 		; jmp ret / return to caller via 'ret'
  2248                              <1> 
  2249                              <1> rcvt:   ; < receive/read character from tty >
  2250                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2251                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2252                              <1> 	;
  2253                              <1> 	; Retro UNIX 8086 v1 modification !
  2254                              <1> 	; 
  2255                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2256                              <1> 	;		(exactly different than this one)
  2257                              <1> 	;	was in 'u9.s' file.
  2258                              <1> 	;
  2259 0000548F 2C0A                <1> 	sub 	al, 10
  2260                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2261                              <1> 	; 16/07/2013
  2262                              <1> 	; 21/05/2013
  2263 00005491 EBBD                <1>         jmp     short rttys
  2264                              <1>       
  2265                              <1> ;rppt: / read paper tape
  2266                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2267                              <1> ;			 / places
  2268                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2269                              <1> ;		       / also enables read bit in prs
  2270                              <1> ;	jsr	r0,passc / place character in users buffer area
  2271                              <1> ;	br	rppt
  2272                              <1> 
  2273                              <1> rmem: ; / transfer characters from memory to a user area of core
  2274                              <1> 	; 17/10/2015
  2275                              <1> 	; 11/06/2015
  2276                              <1> 	; 24/05/2015
  2277                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2278                              <1> 	;
  2279 00005493 8B35[6C6F0000]      <1> 	mov     esi, [u.fofp]
  2280                              <1> rmem_1:
  2281 00005499 8B1E                <1>         mov     ebx, [esi]        
  2282                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2283                              <1> 		               ; / to be transferred to user
  2284 0000549B FF06                <1>         inc     dword [esi] ; 17/10/2015
  2285                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2286                              <1> 			    ; / char in memory file
  2287 0000549D 8A03                <1> 	mov	al, [ebx]
  2288                              <1> 		; movb (r1),r1 / get character from memory file, 
  2289                              <1> 		             ; / put it in r1
  2290 0000549F E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2291                              <1> 			     ;  / the next byte of the users core area
  2292                              <1> 		; br rmem / continue
  2293 000054A4 75F3                <1> 	jnz	short rmem_1
  2294                              <1> ret_:
  2295 000054A6 58                  <1> 	pop	eax ; 09/06/2015
  2296 000054A7 C3                  <1> 	retn
  2297                              <1> 
  2298                              <1> rlpr:
  2299                              <1> ;1:
  2300                              <1> ;rcrd:
  2301 000054A8 C705[AB6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2301 000054B0 0000                <1>
  2302 000054B2 E924E6FFFF          <1> 	jmp	error
  2303                              <1> 		;jmp	error / see 'error' routine
  2304                              <1> 
  2305                              <1> dskr:
  2306                              <1> 	; 12/10/2015
  2307                              <1> 	; 21/08/2015
  2308                              <1> 	; 25/07/2015
  2309                              <1> 	; 10/07/2015
  2310                              <1> 	; 16/06/2015
  2311                              <1> 	; 31/05/2015
  2312                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2313                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2314                              <1> dskr_0:
  2315 000054B7 50                  <1> 	push	eax
  2316                              <1> 		; mov (sp),r1 / i-number in r1
  2317                              <1> 	; AX = i-number
  2318 000054B8 E834FDFFFF          <1> 	call	iget
  2319                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2320 000054BD 0FB715[5C6C0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2321                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2322 000054C4 8B1D[6C6F0000]      <1> 	mov	ebx, [u.fofp]
  2323 000054CA 2B13                <1> 	sub	edx, [ebx]
  2324                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2325                              <1>         ; 12/10/2015
  2326                              <1> 	; jna     short ret_ 
  2327                              <1> 		; blos ret
  2328 000054CC 7709                <1> 	ja	short dskr_1
  2329                              <1> 	;
  2330                              <1> dskr_retn: ; 12/10/2015
  2331 000054CE 58                  <1> 	pop	eax
  2332 000054CF C605[BD6F0000]00    <1> 	mov	byte [u.kcall], 0
  2333 000054D6 C3                  <1> 	retn	
  2334                              <1> dskr_1: 
  2335 000054D7 3B15[806F0000]      <1> 	cmp     edx, [u.count] 
  2336                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2337                              <1> 			       ; / to carry out read
  2338 000054DD 7306                <1> 	jnb	short dskr_2
  2339                              <1> 		; bhis 1f
  2340 000054DF 8915[806F0000]      <1> 	mov	[u.count], edx
  2341                              <1> 		; mov r2,u.count / no, just read to end of file
  2342                              <1> dskr_2: ; 1:
  2343                              <1> 	; AX = i-number
  2344 000054E5 E89EFBFFFF          <1> 	call	mget
  2345                              <1> 		; jsr r0,mget / returns physical block number of block 
  2346                              <1> 			    ; / in file where offset points
  2347                              <1> 	; eAX = physical block number
  2348 000054EA E83F080000          <1> 	call	dskrd
  2349                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2350                              <1> 			     ; / 1st word of data in buffer
  2351                              <1> 	; 09/06/2015
  2352 000054EF 803D[BD6F0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2353 000054F6 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2354 000054F8 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0
  2355 00005500 7705                <1> 	ja	short dskr_4
  2356                              <1> dskr_3:
  2357                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2358 00005502 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2359                              <1> dskr_4:
  2360                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2361 00005507 E8BC020000          <1> 	call	sioreg
  2362                              <1> 		; jsr r0,sioreg
  2363 0000550C 87F7                <1> 	xchg	esi, edi
  2364                              <1> 	; eDI = file (user data) offset
  2365                              <1> 	; eSI = sector (I/O) buffer offset
  2366                              <1> 	; eCX = byte count
  2367 0000550E F3A4                <1> 	rep	movsb
  2368                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2369                              <1> 		                 ; / starting at u.base
  2370                              <1> 		; dec r3
  2371                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2372                              <1> 	; 25/07/2015
  2373                              <1> 	; eax = remain bytes in buffer
  2374                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2375 00005510 09C0                <1> 	or	eax, eax
  2376 00005512 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2377                              <1> 	; 03/08/2013
  2378                              <1> 	;pop	eax
  2379 00005514 390D[806F0000]      <1> 	cmp	[u.count], ecx ; 0
  2380                              <1> 		; tst u.count / all bytes read off disk
  2381                              <1> 		; bne dskr
  2382                              <1> 		; br ret
  2383                              <1>         ;ja      short dskr_0
  2384                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2385                              <1> 	;retn
  2386                              <1> 	; 12/10/2015
  2387 0000551A 76B2                <1> 	jna	short dskr_retn
  2388 0000551C 58                  <1> 	pop	eax  ; (i-node number)
  2389 0000551D EB98                <1> 	jmp	short dskr_0
  2390                              <1> 	
  2391                              <1> passc:
  2392                              <1> 	; 18/10/2015
  2393                              <1> 	; 10/07/2015
  2394                              <1> 	; 01/07/2015
  2395                              <1> 	; 08/06/2015
  2396                              <1> 	; 04/06/2015
  2397                              <1> 	; 20/05/2015
  2398                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2399                              <1> 	;
  2400                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2401                              <1> 	;		      to physical address
  2402 0000551F 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2403                              <1> 			     ; 1-4095 --> use previous physical base address
  2404                              <1> 			     ; in [u.pbase]
  2405 00005527 7705                <1> 	ja	short passc_3
  2406                              <1> 	; 08/06/2015 - 10/07/2015
  2407 00005529 E82C000000          <1> 	call	trans_addr_w
  2408                              <1> passc_3:
  2409                              <1> 	; 19/05/2015
  2410 0000552E 66FF0D[BB6F0000]    <1> 	dec	word [u.pcount]
  2411                              <1> 	;
  2412 00005535 8B1D[B76F0000]      <1> 	mov	ebx, [u.pbase]
  2413 0000553B 8803                <1> 	mov	[ebx], al
  2414                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2415                              <1> 		               ; / users buffer
  2416 0000553D FF05[7C6F0000]      <1> 	inc	dword [u.base]
  2417                              <1> 		; inc u.base / increment the pointer to point to 
  2418                              <1> 			  ; / the next byte in users buffer
  2419 00005543 FF05[B76F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2420 00005549 FF05[846F0000]      <1> 	inc	dword [u.nread]
  2421                              <1> 		; inc u.nread / increment the number of bytes read
  2422 0000554F FF0D[806F0000]      <1> 	dec	dword [u.count]
  2423                              <1> 		; dec u.count / decrement the number of bytes to be read
  2424                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2425 00005555 C3                  <1> 	retn
  2426                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2427                              <1> 		             ; / 'readi' by:
  2428                              <1> 		;/ (1) pop the return address off the stack into r0
  2429                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2430                              <1> 	;1:
  2431                              <1> 		; clr	*$ps / clear processor status
  2432                              <1> 		; rts r0 / return to address currently on top of stack
  2433                              <1> 
  2434                              <1> trans_addr_r:
  2435                              <1> 	; Translate virtual address to physical address 
  2436                              <1> 	; for reading from user's memory space
  2437                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2438                              <1> 	; 18/10/2015
  2439                              <1> 	; 10/07/2015
  2440                              <1> 	; 09/06/2015
  2441                              <1> 	; 08/06/2015 
  2442                              <1> 	; 04/06/2015
  2443                              <1> 	;
  2444                              <1> 	; 18/10/2015
  2445 00005556 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2446 00005558 EB04                <1> 	jmp 	short trans_addr_rw
  2447                              <1> 
  2448                              <1> 	;push	eax
  2449                              <1> 	;push	ebx
  2450                              <1> 	;mov	ebx, [u.base]
  2451                              <1> 	;call	get_physical_addr ; get physical address
  2452                              <1> 	;;jnc	short cpass_0
  2453                              <1> 	;jnc	short passc_1
  2454                              <1> 	;mov	[u.error], eax
  2455                              <1> 	;;pop	ebx
  2456                              <1> 	;;pop	eax
  2457                              <1> 	;jmp	error
  2458                              <1> ;cpass_0:
  2459                              <1> 	; 18/10/2015
  2460                              <1> 	; 20/05/2015
  2461                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2462                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2463                              <1> 	;pop	ebx
  2464                              <1> 	;pop	eax
  2465                              <1> 	;retn	; 08/06/2015
  2466                              <1> 
  2467                              <1> 	; 03/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  2468                              <1> trans_addr_w:
  2469                              <1> 	; Translate virtual address to physical address 
  2470                              <1> 	; for writing to user's memory space
  2471                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2472                              <1> 	; 18/10/2015
  2473                              <1> 	; 29/07/2015
  2474                              <1> 	; 10/07/2015
  2475                              <1> 	; 09/06/2015
  2476                              <1> 	; 08/06/2015
  2477                              <1> 	; 04/06/2015 (passc)
  2478                              <1> 	;
  2479                              <1> 	; 18/10/2015
  2480 0000555A 29D2                <1> 	sub	edx, edx
  2481 0000555C FEC2                <1> 	inc	dl ; 1 (write access sign)
  2482                              <1> trans_addr_rw:
  2483 0000555E 50                  <1> 	push	eax
  2484 0000555F 53                  <1> 	push	ebx
  2485                              <1> 	; 18/10/2015
  2486 00005560 52                  <1> 	push 	edx ; r/w sign (in DL)
  2487                              <1> 	;
  2488 00005561 8B1D[7C6F0000]      <1> 	mov	ebx, [u.base]
  2489 00005567 E854DCFFFF          <1> 	call	get_physical_addr ; get physical address
  2490 0000556C 730A                <1> 	jnc	short passc_0
  2491 0000556E A3[AB6F0000]        <1> 	mov	[u.error], eax
  2492                              <1> 	;pop	edx
  2493                              <1> 	;pop 	ebx
  2494                              <1> 	;pop	eax
  2495 00005573 E963E5FFFF          <1> 	jmp	error
  2496                              <1> passc_0:
  2497 00005578 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2498 0000557B 5A                  <1> 	pop	edx ; 18/10/2015
  2499 0000557C 7517                <1> 	jnz	short passc_1
  2500                              <1> 	; 18/10/2015
  2501 0000557E 20D2                <1> 	and 	dl, dl
  2502 00005580 7413                <1> 	jz	short passc_1
  2503                              <1> 	; 20/05/2015
  2504                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2505                              <1> 	; EBX = linear address
  2506 00005582 51                  <1> 	push 	ecx
  2507 00005583 53                  <1> 	push	ebx ; * ; 03/02/2022 (BugFix)
  2508 00005584 E8A6DBFFFF          <1> 	call 	copy_page
  2509 00005589 5B                  <1> 	pop	ebx ; * ; 03/02/2022 (BugFix)
  2510 0000558A 59                  <1> 	pop	ecx
  2511 0000558B 7217                <1> 	jc	short passc_2
  2512                              <1> 	; 03/02/2022
  2513                              <1> 	;push	eax ; physical address of the new/allocated page
  2514                              <1> 	;call	add_to_swap_queue
  2515                              <1> 	;pop	eax
  2516                              <1> 	; 18/10/2015
  2517 0000558D 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2518                              <1> 	;mov 	ecx, PAGE_SIZE
  2519                              <1> 	;sub	ecx, ebx 
  2520 00005593 01D8                <1> 	add	eax, ebx  
  2521                              <1> passc_1: 
  2522                              <1> 	; 18/10/2015
  2523                              <1> 	; 20/05/2015
  2524 00005595 A3[B76F0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2525 0000559A 66890D[BB6F0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2526 000055A1 5B                  <1> 	pop	ebx
  2527 000055A2 58                  <1> 	pop	eax
  2528 000055A3 C3                  <1> 	retn	; 08/06/2015
  2529                              <1> passc_2:
  2530 000055A4 C705[AB6F0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2530 000055AC 0000                <1>
  2531                              <1> 	;pop 	ebx
  2532                              <1> 	;pop	eax
  2533 000055AE E928E5FFFF          <1> 	jmp	error
  2534                              <1> 
  2535                              <1> writei:
  2536                              <1> 	; 03/02/2022
  2537                              <1> 	; 20/05/2015
  2538                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2539                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2540                              <1> 	;
  2541                              <1> 	; Write data to file with inode number in R1
  2542                              <1> 	; 
  2543                              <1> 	; INPUTS ->
  2544                              <1> 	;    r1 - inode number
  2545                              <1> 	;    u.count - byte count to be written
  2546                              <1> 	;    u.base - points to user buffer
  2547                              <1> 	;    u.fofp - points to word with current file offset
  2548                              <1> 	; OUTPUTS ->
  2549                              <1> 	;    u.count - cleared
  2550                              <1> 	;    u.nread - accumulates total bytes passed back	
  2551                              <1> 	; ((AX = R1))
  2552                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2553                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2554                              <1> 
  2555 000055B3 31C9                <1> 	xor	ecx, ecx
  2556 000055B5 890D[846F0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2557                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2558                              <1> 		            ; / read or write calls
  2559 000055BB 66890D[BB6F0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2560 000055C2 390D[806F0000]      <1> 	cmp 	[u.count], ecx
  2561                              <1> 	;	; tst u.count / test the byte count specified by the user
  2562 000055C8 7701                <1> 	ja 	short writei_1 ; 1f
  2563                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2564 000055CA C3                  <1> 	retn
  2565                              <1> 	;	; rts r0 / no, return - no writing to do
  2566                              <1> writei_1: ;1:
  2567                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2568 000055CB 6683F828            <1> 	cmp 	ax, 40
  2569                              <1> 		; cmp r1,$40.
  2570                              <1> 		; / does the i-node number indicate a special file?
  2571                              <1> 	;ja	dskw 
  2572                              <1> 		; bgt dskw / no, branch to standard file output
  2573                              <1> 	; 03/02/2022
  2574 000055CF 7605                <1> 	jna	short writei_3
  2575 000055D1 E9ED000000          <1> 	jmp	dskw
  2576                              <1> writei_3:
  2577                              <1> 	; (20/05/2015)
  2578 000055D6 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2579 000055D7 0FB6D8              <1> 	movzx	ebx, al
  2580                              <1> 	; 03/02/2022
  2581 000055DA C1E302              <1> 	shl	ebx, 2
  2582                              <1> 	;shl	bx, 2
  2583                              <1> 		; asl r1 / yes, calculate the index into the special file
  2584 000055DD 81C3[E1550000]      <1> 	add	ebx, writei_2 - 4
  2585 000055E3 FF23                <1> 	jmp	dword [ebx]	
  2586                              <1> 		; jmp *1f-2(r1)
  2587                              <1> 		; / jump table and jump to the appropriate routine
  2588                              <1> writei_2: ;1:
  2589 000055E5 [31560000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2590                              <1> 		 ;wtty / tty; r1=2
  2591                              <1> 		 ;wppt / ppt; r1=4
  2592 000055E9 [93560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2593                              <1> 		 ;wmem / mem; r1=6
  2594                              <1> 		 ;wrf0 / rf0
  2595                              <1> 		 ;wrk0 / rk0
  2596                              <1> 		 ;wtap / tap0
  2597                              <1> 		 ;wtap / tap1
  2598                              <1> 		 ;wtap / tap2
  2599                              <1> 		 ;wtap / tap3
  2600                              <1> 		 ;wtap / tap4
  2601                              <1> 		 ;wtap / tap5
  2602                              <1> 		 ;wtap / tap6
  2603                              <1> 		 ;wtap / tap7
  2604 000055ED [685C0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2605 000055F1 [685C0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2606 000055F5 [685C0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2607 000055F9 [685C0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2608 000055FD [685C0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2609 00005601 [685C0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2610 00005605 [84560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2611 00005609 [7E560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2612                              <1> 		 ;xmtt / tty0
  2613 0000560D [7E560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2614                              <1> 		 ;xmtt / tty1
  2615 00005611 [7E560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2616                              <1> 		 ;xmtt / tty2
  2617 00005615 [7E560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2618                              <1> 		 ;xmtt / tty3
  2619 00005619 [7E560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2620                              <1> 		 ;xmtt / tty4
  2621 0000561D [7E560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2622                              <1> 		 ;xmtt / tty5
  2623 00005621 [7E560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2624                              <1> 		 ;xmtt / tty6
  2625 00005625 [7E560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2626                              <1> 		 ;xmtt / tty7
  2627 00005629 [7E560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2628                              <1> 		; / wlpr / lpr
  2629 0000562D [7E560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2630                              <1> 
  2631                              <1> wtty: ; write to console tty (write to screen)
  2632                              <1> 	; 03/02/2022
  2633                              <1> 	; 18/11/2015
  2634                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2635                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2636                              <1> 	;
  2637                              <1> 	; Console tty output is on current video page
  2638                              <1> 	; Console tty character output procedure is changed here
  2639                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2640                              <1> 	;
  2641 00005631 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2642 00005638 8AA3[B76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2643 0000563E 88E0                <1> 	mov	al, ah ; 07/07/2014
  2644                              <1> wttys:	
  2645                              <1> 	; 10/10/2013
  2646 00005640 8825[AA6F0000]      <1> 	mov 	[u.ttyn], ah
  2647                              <1> 	; 13/01/2014
  2648 00005646 FEC0                <1> 	inc	al
  2649 00005648 A2[8D6F0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2650                              <1> wtty_nc: ; 15/05/2013
  2651                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2652 0000564D E816010000          <1> 	call	cpass
  2653                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2654                              <1> 		             ; / none go to return address in syswrite
  2655                              <1> 		; tst r1 / is character = null
  2656                              <1> 		; beq wtty / yes, get next character
  2657                              <1> 	; 10/10/2013
  2658 00005652 7428                <1> 	jz	short wret
  2659                              <1> 	;1 :
  2660                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2661                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2662                              <1> 		;	          / than 20
  2663                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2664                              <1> 	; 27/06/2014
  2665                              <1> wtty_1:
  2666                              <1> 	; AH = tty number
  2667                              <1> 	; AL = ASCII code of the character
  2668                              <1> 	; 15/04/2014
  2669                              <1> 	;push	ax
  2670                              <1> 	; 03/02/2022
  2671 00005654 50                  <1> 	push	eax
  2672 00005655 E8430A0000          <1> 	call	putc ; 14/05/2013
  2673 0000565A 731D                <1> 	jnc	short wtty_2
  2674                              <1> 	; 18/11/2015
  2675 0000565C E822F9FFFF          <1> 	call	idle
  2676                              <1> 	;mov	ax, [esp]
  2677                              <1> 	; 03/02/2022
  2678 00005661 8B0424              <1> 	mov	eax, [esp]
  2679 00005664 E8340A0000          <1> 	call	putc
  2680 00005669 730E                <1> 	jnc	short wtty_2 
  2681                              <1> 	; 02/06/2014
  2682 0000566B 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn]
  2683 00005671 E89AF9FFFF          <1> 	call	sleep
  2684                              <1> 	; 03/02/2022
  2685 00005676 58                  <1> 	pop	eax
  2686                              <1> 	;pop	ax
  2687 00005677 EBDB                <1> 	jmp 	short wtty_1
  2688                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2689                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2690                              <1> 			      ; / console tty and
  2691                              <1> 		; br 	2f / place character in list; if none available
  2692                              <1> 		   	  ; / branch to put process to sleep
  2693                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2694                              <1> wtty_2:
  2695                              <1> 	; 15/04/2014
  2696                              <1> 	;pop	ax
  2697                              <1> 	; 03/02/2022
  2698 00005679 58                  <1> 	pop	eax
  2699 0000567A EBD1                <1> 	jmp	short wtty_nc
  2700                              <1> 		; br wtty
  2701                              <1> wret:	; 10/10/2013 (20/05/2015)
  2702 0000567C 58                  <1> 	pop	eax
  2703 0000567D C3                  <1> 	retn
  2704                              <1> 	;2:
  2705                              <1> 		;mov	r1,-(sp) / place character on stack
  2706                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2707                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2708                              <1> 		;br	1b / try again to place character in clist and output
  2709                              <1> 
  2710                              <1> xmtt:   ; < send/write character to tty >
  2711                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2712                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2713                              <1> 	;
  2714                              <1> 	; Retro UNIX 8086 v1 modification !
  2715                              <1> 	; 
  2716                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2717                              <1> 	;		(exactly different than this one)
  2718                              <1> 	;	was in 'u9.s' file.
  2719                              <1> 	;
  2720 0000567E 2C0A                <1> 	sub 	al, 10
  2721                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2722                              <1> 	; 10/10/2013
  2723 00005680 88C4                <1> 	mov	ah, al
  2724                              <1> 	; 28/07/2013
  2725 00005682 EBBC                <1> 	jmp	short wttys
  2726                              <1> 
  2727                              <1> ;wppt:
  2728                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2729                              <1> ;		         / if none return to writei's calling routine
  2730                              <1> ;	jsr	r0,pptoc / output character on ppt
  2731                              <1> ;	br	wppt
  2732                              <1> wlpr:
  2733 00005684 C705[AB6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2733 0000568C 0000                <1>
  2734 0000568E E948E4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2735                              <1> 		;/	jsr	r0,cpass
  2736                              <1> 		;/	cmp	r0,$'a
  2737                              <1> 		;/	blo	1f
  2738                              <1> 		;/	cmp	r1,$'z
  2739                              <1> 		;/	bhi	1f
  2740                              <1> 		;/	sub	$40,r1
  2741                              <1> 		;/1:
  2742                              <1> 		;/	jsr	r0,lptoc
  2743                              <1> 		;/	br	wlpr
  2744                              <1> 		; br rmem / continue
  2745                              <1> 
  2746                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2747                              <1> 	; 17/10/2015
  2748                              <1> 	; 11/06/2015
  2749                              <1> 	; 24/05/2015
  2750                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2751                              <1> 	;
  2752 00005693 813D[28070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2752 00005699 [A64F0000]          <1>
  2753 0000569D 7415                <1>         je      short wmem_acc_err
  2754                              <1> 	;
  2755 0000569F 8B35[6C6F0000]      <1>         mov     esi, [u.fofp] 
  2756                              <1> wmem_1:
  2757 000056A5 E8BE000000          <1> 	call	cpass
  2758                              <1> 		; jsr r0,cpass / get next character from users area of
  2759                              <1> 			     ; / core and put it in r1
  2760                              <1>         	; mov r1,-(sp) / put character on the stack
  2761                              <1> 	; 20/09/2013
  2762 000056AA 74D0                <1> 	jz	short wret ; wmem_2  
  2763 000056AC 8B1E                <1>         mov     ebx, [esi]
  2764                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2765 000056AE FF06                <1>         inc     dword [esi] ; 17/10/2015
  2766                              <1> 		; inc *u.fofp / increment file offset to point to next
  2767                              <1> 			    ; / available location in file
  2768 000056B0 8803                <1> 	mov	[ebx], al	
  2769                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2770                              <1> 			        ; / assigned to it
  2771 000056B2 EBF1                <1> 	jmp	short wmem_1
  2772                              <1> 		; br wmem / continue
  2773                              <1> 	;1:
  2774                              <1> 	;jmp	error / ?
  2775                              <1> ;wmem_2:	
  2776                              <1> ;	; 20/09/2013
  2777                              <1> ;	pop	ax
  2778                              <1> ;	retn
  2779                              <1> 
  2780                              <1> wmem_acc_err:
  2781 000056B4 C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2781 000056BC 0000                <1>
  2782 000056BE E918E4FFFF          <1> 	jmp	error
  2783                              <1> 
  2784                              <1> dskw: ; / write routine for non-special files
  2785                              <1> 	;
  2786                              <1> 	; 03/02/2022
  2787                              <1> 	; 25/07/2015
  2788                              <1> 	; 16/06/2015
  2789                              <1> 	; 09/06/2015
  2790                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2791                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2792                              <1> 	;
  2793                              <1> 	; 01/08/2013 (mkdir_w check)
  2794                              <1> 
  2795                              <1> 	;push	ax ; 26/04/2013
  2796                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2797                              <1> 	; 03/02/2022
  2798 000056C3 50                  <1> 	push	eax
  2799                              <1> 	; AX = inode number
  2800 000056C4 E828FBFFFF          <1> 	call	iget
  2801                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2802                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2803 000056C9 8B1D[6C6F0000]      <1>         mov     ebx, [u.fofp] 
  2804 000056CF 8B13                <1> 	mov 	edx, [ebx]
  2805                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2806                              <1> 			       ; / in the fsp entry for this file] in r2
  2807 000056D1 0315[806F0000]      <1> 	add 	edx, [u.count]	
  2808                              <1> 		; add u.count,r2 / no. of bytes to be written
  2809                              <1> 			       ; / + file offset is put in r2
  2810                              <1> 	; 16/06/2015        
  2811 000056D7 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2812 000056DD 760F                <1> 	jna	short dskw_0
  2813 000056DF C705[AB6F0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2813 000056E7 0000                <1>
  2814 000056E9 E9EDE3FFFF          <1> 	jmp	error
  2815                              <1> dskw_0:	
  2816 000056EE 663B15[5C6C0000]    <1> 	cmp     dx, [i.size]
  2817                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2818                              <1> 		              ; / the file?
  2819 000056F5 760C                <1> 	jna	short dskw_1
  2820                              <1> 		; blos 1f / no, branch
  2821 000056F7 668915[5C6C0000]    <1>         mov     [i.size], dx
  2822                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2823                              <1> 			      ; / file offset + no. of data bytes
  2824 000056FE E8F8FBFFFF          <1> 	call	setimod
  2825                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2826                              <1> 		          ; / modified), stuff time of modification into
  2827                              <1> 	          	  ; / core image of i-node
  2828                              <1> dskw_1: ; 1:	
  2829 00005703 E880F9FFFF          <1> 	call	mget
  2830                              <1> 	; eAX = Block number
  2831                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2832                              <1> 			    ; /	the next data byte
  2833                              <1> 	; eax = block number
  2834 00005708 8B1D[6C6F0000]      <1> 	mov     ebx, [u.fofp]
  2835 0000570E 8B13                <1> 	mov	edx, [ebx]
  2836 00005710 81E2FF010000        <1> 	and	edx, 1FFh  
  2837                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2838 00005716 750C                <1> 	jnz	short dskw_2
  2839                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2840                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2841 00005718 813D[806F0000]0002- <1> 	cmp	dword [u.count], 512
  2841 00005720 0000                <1>
  2842                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2843                              <1> 				  ; / an entire block? (i.e., no. of
  2844 00005722 7305                <1> 	jnb	short dskw_3
  2845                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2846                              <1> 			; / Yes, branch. Don't have to read block
  2847                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2848                              <1>    		; / overwritten).
  2849 00005724 E805060000          <1> 	call	dskrd
  2850                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2851                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2852                              <1> dskw_3: ; 3:
  2853                              <1> 	; eAX (r1) = block/sector number
  2854 00005729 E872060000          <1> 	call	wslot
  2855                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2856                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2857 0000572E 803D[BD6F0000]00    <1> 	cmp	byte [u.kcall], 0
  2858 00005735 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2859                              <1> 	;
  2860 00005737 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0
  2861 0000573F 7705                <1> 	ja	short dskw_5
  2862                              <1> dskw_4:
  2863                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2864 00005741 E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2865                              <1> dskw_5:
  2866                              <1> 	; eBX (r5) = system (I/O) buffer address
  2867 00005746 E87D000000          <1> 	call	sioreg
  2868                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2869                              <1> 			     ; / r1 = address of data, r2 points to location
  2870                              <1> 			     ; / in buffer in which to start writing data
  2871                              <1> 	; eSI = file (user data) offset
  2872                              <1> 	; eDI = sector (I/O) buffer offset
  2873                              <1> 	; eCX = byte count
  2874                              <1> 	;
  2875 0000574B F3A4                <1>   	rep	movsb
  2876                              <1> 		; movb (r1 )+,(r2)+ 
  2877                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2878                              <1> 		; dec r3 / decrement no. of bytes to be written
  2879                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2880                              <1> 	; 25/07/2015
  2881                              <1> 	; eax = remain bytes in buffer
  2882                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2883 0000574D 09C0                <1> 	or	eax, eax
  2884 0000574F 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2885                              <1> dskw_6:
  2886 00005751 E866060000          <1> 	call	dskwr
  2887                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2888 00005756 833D[806F0000]00    <1>         cmp     dword [u.count], 0
  2889                              <1> 		; tst u.count / any more data to write?
  2890 0000575D 77A4                <1> 	ja	short dskw_1
  2891                              <1> 		; bne 1b / yes, branch
  2892                              <1> 	; 03/08/2013
  2893 0000575F C605[BD6F0000]00    <1> 	mov	byte [u.kcall], 0
  2894                              <1> 	; 20/09/2013 (;;)
  2895                              <1> 	;pop	ax
  2896                              <1> 	; 03/02/2022
  2897 00005766 58                  <1> 	pop	eax
  2898 00005767 C3                  <1> 	retn
  2899                              <1> 	;;jmp 	short dskw_ret 
  2900                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2901                              <1> 
  2902                              <1> cpass: ; / get next character from user area of core and put it in r1
  2903                              <1> 	; 18/10/2015
  2904                              <1> 	; 10/10/2015
  2905                              <1> 	; 10/07/2015
  2906                              <1> 	; 02/07/2015
  2907                              <1> 	; 01/07/2015
  2908                              <1> 	; 24/06/2015
  2909                              <1> 	; 08/06/2015
  2910                              <1> 	; 04/06/2015
  2911                              <1> 	; 20/05/2015
  2912                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2913                              <1> 	;
  2914                              <1> 	; INPUTS -> 
  2915                              <1> 	;     [u.base] = virtual address in user area
  2916                              <1> 	;     [u.count] = byte count (max.)
  2917                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2918                              <1> 	; OUTPUTS -> 
  2919                              <1> 	;     AL = the character which is pointed by [u.base]
  2920                              <1> 	;     zf = 1 -> transfer count has been completed	
  2921                              <1>         ;
  2922                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2923                              <1> 	;
  2924                              <1> 	;
  2925 00005768 833D[806F0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2926                              <1> 		; tst u.count / have all the characters been transferred
  2927                              <1> 			    ; / (i.e., u.count, # of chars. left
  2928 0000576F 763F                <1> 	jna	short cpass_3
  2929                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2930 00005771 FF0D[806F0000]      <1> 	dec	dword [u.count]
  2931                              <1> 		; dec u.count / no, decrement u.count
  2932                              <1>         ; 19/05/2015 
  2933                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2934                              <1> 	;		      to physical address
  2935 00005777 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2936                              <1> 			     ; 1-4095 --> use previous physical base address
  2937                              <1> 			     ; in [u.pbase]
  2938 0000577F 770E                <1> 	ja	short cpass_1
  2939                              <1> 	; 02/07/2015
  2940 00005781 833D[B36F0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2941 00005788 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2942                              <1> 	; 08/06/2015 - 10/07/2015
  2943 0000578A E8C7FDFFFF          <1> 	call	trans_addr_r
  2944                              <1> cpass_1:
  2945                              <1> 	; 02/07/2015
  2946                              <1> 	; 24/06/2015
  2947 0000578F 66FF0D[BB6F0000]    <1> 	dec	word [u.pcount]
  2948                              <1> cpass_2: 
  2949                              <1> 	; 10/10/2015
  2950                              <1> 	; 02/07/2015
  2951 00005796 8B15[B76F0000]      <1> 	mov	edx, [u.pbase]
  2952 0000579C 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  2953                              <1> 		; movb *u.base,r1 / take the character pointed to 
  2954                              <1> 				; / by u.base and put it in r1
  2955 0000579E FF05[846F0000]      <1> 	inc	dword [u.nread]
  2956                              <1> 		; inc u.nread / increment no. of bytes transferred
  2957 000057A4 FF05[7C6F0000]      <1> 	inc	dword [u.base]
  2958                              <1> 		; inc u.base / increment the buffer address to point to the
  2959                              <1> 			   ; / next byte
  2960 000057AA FF05[B76F0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2961                              <1> cpass_3:
  2962 000057B0 C3                  <1> 	retn
  2963                              <1> 		; rts	r0 / next byte
  2964                              <1> 	; 1: 
  2965                              <1> 		; mov (sp)+,r0 
  2966                              <1> 		         ; / put return address of calling routine into r0
  2967                              <1> 		; mov (sp)+,r1 / i-number in r1
  2968                              <1> 		; rts r0 / non-local return
  2969                              <1> cpass_k:
  2970                              <1> 	; 02/07/2015
  2971                              <1> 	; The caller is os kernel 
  2972                              <1> 	; (get sysexec arguments from kernel's memory space)
  2973                              <1> 	;
  2974 000057B1 8B1D[7C6F0000]      <1> 	mov	ebx, [u.base]
  2975 000057B7 66C705[BB6F0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  2975 000057BF 10                  <1>
  2976 000057C0 891D[B76F0000]      <1> 	mov	[u.pbase], ebx
  2977 000057C6 EBCE                <1> 	jmp	short cpass_2
  2978                              <1> 	
  2979                              <1> sioreg: 
  2980                              <1> 	; 25/07/2015
  2981                              <1> 	; 18/07/2015
  2982                              <1> 	; 02/07/2015
  2983                              <1> 	; 17/06/2015
  2984                              <1> 	; 09/06/2015
  2985                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2986                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  2987                              <1> 	;
  2988                              <1> 	; INPUTS -> 
  2989                              <1> 	;     eBX = system buffer (data) address (r5)
  2990                              <1> 	;     [u.fofp] = pointer to file offset pointer
  2991                              <1> 	;     [u.base] = virtual address of the user buffer
  2992                              <1> 	;     [u.pbase] = physical address of the user buffer
  2993                              <1> 	;     [u.count] = byte count
  2994                              <1> 	;     [u.pcount] = byte count within page frame 			
  2995                              <1> 	; OUTPUTS -> 
  2996                              <1> 	;     eSI = user data offset (r1)
  2997                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  2998                              <1> 	;     eCX = byte count (r3)
  2999                              <1> 	;     EAX = remain bytes after byte count within page frame
  3000                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3001                              <1>         ;
  3002                              <1> 	; ((Modified registers:  EDX))
  3003                              <1>  
  3004 000057C8 8B35[6C6F0000]      <1>         mov     esi, [u.fofp]
  3005 000057CE 8B3E                <1>         mov     edi, [esi]
  3006                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3007 000057D0 89F9                <1> 	mov	ecx, edi
  3008                              <1> 		; mov r2,r3 / and also to r3
  3009 000057D2 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3010                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3011 000057D8 81E7FF010000        <1> 	and	edi, 1FFh
  3012                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3013 000057DE 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3014                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3015                              <1> 			  ; / where data is to be placed
  3016                              <1>                 ; mov u.base,r1 / address of data is in r1
  3017 000057E0 F7D9                <1> 	neg	ecx
  3018                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3019                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3020 000057E2 3B0D[806F0000]      <1> 	cmp	ecx, [u.count]
  3021                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3022                              <1> 			       ; / to be written to the file
  3023 000057E8 7606                <1> 	jna	short sioreg_0
  3024                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3025                              <1> 			 ; / in the file block as the number to be written
  3026 000057EA 8B0D[806F0000]      <1> 	mov	ecx, [u.count]
  3027                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3028                              <1> 			       ; / bytes as the number to be written
  3029                              <1> sioreg_0:
  3030                              <1> 	; 17/06/2015
  3031 000057F0 803D[BD6F0000]00    <1> 	cmp	byte [u.kcall], 0 
  3032 000057F7 7613                <1> 	jna	short sioreg_1
  3033                              <1> 	; 25/07/2015
  3034                              <1> 	; the caller is 'mkdir' or 'namei'
  3035 000057F9 A1[7C6F0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3036 000057FE A3[B76F0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3037 00005803 66890D[BB6F0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3038 0000580A EB0B                <1> 	jmp	short sioreg_2
  3039                              <1> sioreg_1:
  3040                              <1> 	; 25/07/2015
  3041                              <1> 	; 18/07/2015
  3042                              <1> 	; 09/06/2015 
  3043 0000580C 0FB715[BB6F0000]    <1> 	movzx	edx, word [u.pcount]
  3044                              <1> 		; ecx and [u.pcount] are always > 0, here
  3045 00005813 39D1                <1> 	cmp	ecx, edx	
  3046 00005815 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3047                              <1> sioreg_2: ; 2:
  3048 00005817 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3049                              <1> sioreg_3:
  3050 00005819 010D[846F0000]      <1> 	add 	[u.nread], ecx
  3051                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3052                              <1> 			         ; / during write is put into u.nread
  3053 0000581F 290D[806F0000]      <1> 	sub 	[u.count], ecx
  3054                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3055                              <1> 			       ; / must be written or read
  3056 00005825 010D[7C6F0000]      <1> 	add 	[u.base], ecx
  3057                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3058                              <1> 			      ; / data bytes
  3059 0000582B 010E                <1>         add 	[esi], ecx 
  3060                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3061                              <1> 			       ; / + old file offset
  3062                              <1> 	; 25/07/2015
  3063 0000582D 8B35[B76F0000]      <1> 	mov	esi, [u.pbase]
  3064 00005833 66290D[BB6F0000]    <1> 	sub	[u.pcount], cx
  3065 0000583A 010D[B76F0000]      <1> 	add	[u.pbase], ecx
  3066 00005840 C3                  <1>         retn
  3067                              <1> 		; rts r0
  3068                              <1> 		; transfer count > [u.pcount]
  3069                              <1> sioreg_4:
  3070                              <1> 	; 25/07/2015
  3071                              <1> 	; transfer count > [u.pcount] 
  3072                              <1> 	; (ecx > edx)
  3073 00005841 89C8                <1> 	mov	eax, ecx
  3074 00005843 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3075 00005845 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3076 00005847 EBD0                <1> 	jmp	short sioreg_3
  2053                                  %include 'u7.s'        ; 18/04/2015
  2054                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYS7.INC
  2055                              <1> ; Last Modification: 15/05/2022
  2056                              <1> ; ----------------------------------------------------------------------------
  2057                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2058                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2059                              <1> ;
  2060                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2061                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2062                              <1> ; <Bell Laboratories (17/3/1972)>
  2063                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2064                              <1> ;
  2065                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2066                              <1> ;
  2067                              <1> ; ****************************************************************************
  2068                              <1> ; 14/11/2015
  2069                              <1> 
  2070                              <1> sysmount: ; / mount file system; args special; name
  2071                              <1> 	; 14/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2072                              <1> 	; 12/02/2022
  2073                              <1> 	; 04/02/2022
  2074                              <1> 	; 14/11/2015
  2075                              <1> 	; 24/10/2015
  2076                              <1> 	; 13/10/2015
  2077                              <1> 	; 10/07/2015
  2078                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2079                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2080                              <1> 	;
  2081                              <1> 	; 'sysmount' anounces to the system that a removable 
  2082                              <1> 	; file system has been mounted on a special file.
  2083                              <1> 	; The device number of the special file is obtained vihha
  2084                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2085                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2086                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2087                              <1> 	; to read file system into core, i.e. the first block on the
  2088                              <1> 	; mountable file system is read in. This block is super block
  2089                              <1> 	; for the file system. This call is super user restricted.	
  2090                              <1> 	;
  2091                              <1> 	; Calling sequence:
  2092                              <1> 	;	sysmount; special; name
  2093                              <1> 	; Arguments:
  2094                              <1> 	;	special - pointer to name of special file (device)
  2095                              <1> 	;	name -  pointer to name of the root directory of the
  2096                              <1> 	;		newly mounted file system. 'name' should 
  2097                              <1> 	;		always be a directory.
  2098                              <1> 	; Inputs: - 
  2099                              <1> 	; Outputs: -
  2100                              <1> 	; ...............................................................
  2101                              <1> 	;				
  2102                              <1> 	; Retro UNIX 8086 v1 modification: 
  2103                              <1> 	;       'sysmount' system call has two arguments; so,
  2104                              <1> 	;	* 1st argument, special is pointed to by BX register
  2105                              <1> 	;	* 2nd argument, name is in CX register
  2106                              <1> 	;
  2107                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2108                              <1> 	;	       already modified for IBM PC compatibility and 
  2109                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2110                              <1> 	
  2111                              <1> 	;call	arg2
  2112                              <1> 		; jsr r0,arg2 / get arguments special and name
  2113 00005849 891D[746F0000]      <1> 	mov	[u.namep], ebx
  2114                              <1> 	; 12/02/2022
  2115                              <1> 	;push	ecx ; directory name
  2116 0000584F 66833D[466F0000]00  <1> 	cmp	word [mnti], 0
  2117                              <1> 		; tst mnti / is the i-number of the cross device file
  2118                              <1> 			 ; / zero?
  2119                              <1> 	;;ja	error
  2120                              <1>         	; bne errora / no, error
  2121                              <1> 	;ja	sysmnt_err0
  2122                              <1> 	; 04/02/2022
  2123 00005857 7605                <1> 	jna	short sysmnt_0
  2124 00005859 E950010000          <1> 	jmp	sysmnt_err0
  2125                              <1> sysmnt_0:
  2126                              <1> 	; 12/02/2022
  2127 0000585E 51                  <1> 	push	ecx ; directory name
  2128 0000585F E859010000          <1> 	call	getspl
  2129                              <1> 		; jsr r0,getspl / get special files device number in r1
  2130                              <1> 	; 12/02/2022
  2131 00005864 8F05[746F0000]      <1> 	pop	dword [u.namep] ; directory name
  2132                              <1> 	; 13/10/2015
  2133                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2134                              <1> 	; 04/02/2022
  2135 0000586A 29DB                <1> 	sub	ebx, ebx
  2136 0000586C 88C3                <1> 	mov	bl, al
  2137 0000586E F683[DA660000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2138 00005875 750F                <1> 	jnz	short sysmnt_1
  2139                              <1> sysmnt_err1:
  2140 00005877 C705[AB6F0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2140 0000587F 0000                <1>
  2141 00005881 E955E2FFFF          <1> 	jmp	error
  2142                              <1> sysmnt_1:
  2143                              <1> 	; 12/02/2022
  2144                              <1> 	;pop	dword [u.namep]
  2145                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2146                              <1> 				  ; / on the device
  2147                              <1> 	; 14/11/2015
  2148 00005886 53                  <1> 	push	ebx ; 13/10/2015
  2149                              <1> 		; mov r1,-(sp) / save the device number
  2150                              <1>         ;
  2151 00005887 E850F1FFFF          <1> 	call	namei
  2152                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2153                              <1> 		       ; ax = 0 -> file not found 	
  2154                              <1> 	;jz	error
  2155                              <1> 	;jc	error
  2156                              <1> 		; jsr r0,namei / get the i-number of the file
  2157                              <1>                	; br errora
  2158 0000588C 730F                <1> 	jnc	short sysmnt_2
  2159                              <1> sysmnt_err2:
  2160 0000588E C705[AB6F0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2160 00005896 0000                <1>
  2161 00005898 E93EE2FFFF          <1> 	jmp	error
  2162                              <1> sysmnt_2:	
  2163 0000589D 66A3[466F0000]      <1> 	mov	[mnti], ax
  2164                              <1>         	; mov r1,mnti / put it in mnti
  2165                              <1> 
  2166                              <1> 	; 14/05/2022
  2167                              <1> 	; -Retro UNIX 8086/386 v1 feaure only-
  2168 000058A3 66A1[3C6F0000]      <1> 	mov	ax, [ii]
  2169 000058A9 66A3[486F0000]      <1> 	mov	[mntp], ax ; parent dir inumber of [mnti]
  2170                              <1> 
  2171                              <1> 	; 04/02/2022
  2172 000058AF BB[147E0000]        <1> 	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2173                              <1> sysmnt_3: ;1:
  2174                              <1>         ;cmp	byte [ebx+1], 0
  2175                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2176                              <1> 			   ; / dismountable device set?
  2177                              <1>         ;jna	short sysmnt_4		
  2178                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2179                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2180                              <1> 	;jmp	short sysmnt_3
  2181                              <1> sysmnt_4:   
  2182 000058B4 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2183 000058B5 A2[436F0000]        <1> 	mov	[mdev], al
  2184                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2185 000058BA 8803                <1> 	mov	[ebx], al
  2186                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2187                              <1> 			      ; / of the I/O queue entry
  2188                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2189                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2190 000058BC 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2191                              <1> 		; bis $2000,sb1 / set the read bit
  2192                              <1> 	; Retro UNIX 386 v1 modification : 
  2193                              <1> 	;	32 bit block number at buffer header offset 4
  2194 000058C1 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2195 000058C8 E83A060000          <1> 	call 	diskio
  2196 000058CD 7345                <1> 	jnc	short sysmnt_5
  2197 000058CF 31C0                <1> 	xor 	eax, eax
  2198 000058D1 66A3[466F0000]      <1> 	mov	[mnti], ax ; 0
  2199 000058D7 A2[436F0000]        <1> 	mov	[mdev], al ; 0
  2200                              <1> 	;mov	[cdev], al ; 0
  2201                              <1> 	; 12/02/2022
  2202 000058DC 803D[BE6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2203 000058E3 7508                <1> 	jne	short sysmnt_err3
  2204                              <1> 	; yes, clear [u.brwdev] for next check
  2205                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2206 000058E5 FE05[BE6F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2207 000058EB EB0A                <1> 	jmp	short sysmnt_err4
  2208                              <1> sysmnt_err3:	; 12/02/2022
  2209                              <1> 	; no, set [u.error] to disk read error
  2210 000058ED C705[AB6F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2210 000058F5 0000                <1>
  2211                              <1> sysmnt_err4:
  2212                              <1> 	; 12/02/2022
  2213                              <1> 	; 14/11/2015
  2214 000058F7 FEC8                <1> 	dec 	al
  2215 000058F9 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2216 000058FB FEC0                <1> 	inc	al
  2217 000058FD 48                  <1> 	dec	eax
  2218 000058FE 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2219 00005901 E9D5E1FFFF          <1> 	jmp	error
  2220                              <1> sysmnt_invd:
  2221                              <1> 	; 12/02/2022
  2222 00005906 C705[AB6F0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2222 0000590E 0000                <1>
  2223                              <1> 				 ;'invalid fs/superblock !' error
  2224 00005910 30C0                <1> 	xor	al, al
  2225 00005912 EBE3                <1> 	jmp	short sysmnt_err4
  2226                              <1> 
  2227                              <1> sysmnt_5:
  2228                              <1> 	; 04/02/2022 (BugFix)
  2229                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2230                              <1> 	; (Following check is needed to prevent mounting an
  2231                              <1> 	; invalid valid file system (invalid super block).
  2232                              <1> 	; 
  2233 00005914 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2234 00005917 C0E002              <1> 	shl	al, 2 ; 4*index
  2235 0000591A 8B88[BE660000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2236                              <1> 	;;shl 	ecx, 3 ; !!!
  2237                              <1> 	; 04/02/2022
  2238 00005920 C1E903              <1> 	shr 	ecx, 3 ; (8 sectors per 1 fbm byte)
  2239                              <1> 	; ecx = number of free map bytes (required)
  2240                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2241 00005923 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)
  2242                              <1> 	; ! Buffer header is 8 bytes (Retro UNIX 386 v1 and v1.1) !
  2243                              <1> 	;;movzx	edx, word [sb1+4] ; the 1st data word ; !!!
  2244 00005927 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2245                              <1> 			 ; (in sectors), if they are not equal
  2246                              <1> 			 ; the disk to be mounted is an...	
  2247 00005929 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2248                              <1> 			 ; (which has not got a valid super block)
  2249                              <1> 	;
  2250 0000592B C6430100            <1> 	mov	byte [ebx+1], 0
  2251                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2252                              <1> ;sysmnt_6: ;1:
  2253                              <1> 	;;cmp	byte [sb1+1], 0
  2254                              <1> 		; tstb sb1+1 / done reading?
  2255                              <1>    	;;jna	sysret
  2256                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2257                              <1> 	;;jmp	short sysmnt_6
  2258                              <1> 		;bne 1b / no, wait
  2259                              <1>         	;br sysreta / yes
  2260 0000592F E9C7E1FFFF          <1> 	jmp	sysret
  2261                              <1> 
  2262                              <1> sysumount: ; / special dismount file system,
  2263                              <1> 	; 15/05/2022
  2264                              <1> 	; 09/05/2022 (Retro UNIX 386 v1.0, Kernel v0.2.0.19)
  2265                              <1> 	; 04/02/2022
  2266                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2267                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2268                              <1> 	;
  2269                              <1> 	; 04/11/2013
  2270                              <1> 	; 09/07/2013
  2271                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2272                              <1> 	; indicated as an argument is no longer contain a removable
  2273                              <1> 	; file system. 'getspl' gets the device number of the special
  2274                              <1> 	; file. If no file system was mounted on that device an error
  2275                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2276                              <1> 	; to 'sysret'.
  2277                              <1> 	;
  2278                              <1> 	; Calling sequence:
  2279                              <1> 	;	sysmount; special
  2280                              <1> 	; Arguments:
  2281                              <1> 	;	special - special file to dismount (device)
  2282                              <1> 	;
  2283                              <1> 	; Inputs: - 
  2284                              <1> 	; Outputs: -
  2285                              <1> 	; ...............................................................
  2286                              <1> 	;				
  2287                              <1> 	; Retro UNIX 8086 v1 modification: 
  2288                              <1> 	;       'sysumount' system call has one argument; so,
  2289                              <1> 	;	* Single argument, special is pointed to by BX register
  2290                              <1> 	;
  2291                              <1> 	
  2292                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2293                              <1> 	;call	arg
  2294                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2295 00005934 891D[746F0000]      <1>         mov	[u.namep], ebx
  2296 0000593A E87E000000          <1> 	call	getspl
  2297                              <1> 		; jsr r0,getspl / get the device number in r1
  2298                              <1> 	;;;
  2299                              <1> 	; 09/05/2022 - Erdogan Tan
  2300                              <1> 	; (I have added [mnti] check because
  2301                              <1> 	;  retro unix device number of /dev/fd0 is 0
  2302                              <1> 	;  .. so, 'cmp al, [mdev]' is not enough
  2303                              <1> 	;  for dismounting /dev/fd0. sysumount system call would give
  2304                              <1> 	;  wrong cf=0 result while /dev/fd0 is not mounted.)
  2305 0000593F 66833D[466F0000]00  <1> 	cmp	word [mnti], 0
  2306 00005947 7665                <1> 	jna	short sysmnt_err0 ; there is not a mounted device !
  2307                              <1> 	;;;
  2308                              <1> 
  2309 00005949 3A05[436F0000]      <1> 	cmp	al, [mdev]
  2310                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2311 0000594F 755D                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2312                              <1> 	;jne	error
  2313                              <1>         	; bne errora / no error
  2314 00005951 30C0                <1> 	xor	al, al ; ah = 0
  2315                              <1> sysumnt_0: ;1:
  2316                              <1>      	; 04/02/2022
  2317                              <1> 	;cmp 	[sb1+1], al ; 0
  2318                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2319                              <1> 	;		   ; / (inhibit bit set)?
  2320                              <1> 	;jna	short sysumnt_1		
  2321                              <1> 	;	; bne 1b / yes, wait
  2322                              <1> 	;call	idle ; (wait for hardware interrupt)
  2323                              <1> 	;jmp	short sysumnt_0
  2324                              <1> sysumnt_1:
  2325                              <1> 	; 15/05/2022
  2326                              <1> 	; change user's current directory to mounting directory
  2327                              <1> 	; if it is on the mounted device (chdir back to root fs)
  2328 00005953 3805[A06F0000]      <1> 	cmp	byte [u.cdrv], al ; 0
  2329 00005959 7643                <1> 	jna	short sysumnt_4
  2330                              <1> 	;;;
  2331                              <1> 	; 15/05/2022
  2332                              <1> 	; It is needed to change the parent process's current
  2333                              <1> 	; directory because shell runs (/etc/umount) 
  2334                              <1> 	; as child process.
  2335 0000595B 31DB                <1> 	xor	ebx, ebx 
  2336 0000595D 8A1D[A56F0000]      <1> 	mov	bl, [u.uno]
  2337 00005963 D0E3                <1> 	shl	bl, 1 ; >= 2 .. <= 32
  2338 00005965 81C3[966C0000]      <1> 	add	ebx, p.ppid-2
  2339 0000596B 668B13              <1> 	mov	dx, [ebx] ; process id of the parent [p.ppid]	
  2340 0000596E BE[786C0000]        <1> 	mov	esi, p.pid
  2341 00005973 29C9                <1> 	sub	ecx, ecx
  2342 00005975 B110                <1> 	mov	cl, nproc ; 16  
  2343                              <1> sysumnt_2:	
  2344 00005977 66AD                <1> 	lodsw
  2345 00005979 6639D0              <1> 	cmp	ax, dx
  2346 0000597C 7402                <1> 	je	short sysumnt_3
  2347 0000597E E2F7                <1> 	loop	sysumnt_2
  2348                              <1> sysumnt_3:
  2349 00005980 31C0                <1> 	xor	eax, eax
  2350 00005982 81EE[786C0000]      <1> 	sub	esi, p.pid
  2351 00005988 D1E6                <1> 	shl	esi, 1
  2352 0000598A 8B9E[E46C0000]      <1> 	mov	ebx, [esi+p.upage-4] ; the parent's upage
  2353                              <1> 	; ebx points to user (u) structure in upage
  2354 00005990 668B15[466F0000]    <1> 	mov	dx, [mnti]
  2355                              <1> 	;mov	[u.cdir], dx
  2356                              <1> 	;mov	[u.cdrv], al ; 0
  2357 00005997 6689530C            <1> 	mov	[ebx+u.cdir-user], dx
  2358 0000599B 88434C              <1> 	mov	[ebx+u.cdrv-user], al ; 0
  2359                              <1> 	;;;
  2360                              <1> sysumnt_4: 
  2361 0000599E A2[436F0000]        <1> 	mov	[mdev], al ; 0
  2362                              <1> 	     	; clr mntd / no, clear these
  2363 000059A3 66A3[466F0000]      <1>    	mov	[mnti], ax ; 0
  2364                              <1>         	; clr mnti
  2365                              <1> 
  2366                              <1> 	;; 15/05/2022
  2367                              <1> 	;mov	[cdev], al ; 0 ; [u.cdrv] = 0
  2368                              <1> 	;mov	ax, dx  ; [u.cdir]
  2369                              <1> 	;call	iget		
  2370                              <1> 
  2371 000059A9 E94DE1FFFF          <1>         jmp	sysret
  2372                              <1> 		; br sysreta / return
  2373                              <1> 
  2374                              <1> sysmnt_err0:
  2375 000059AE C705[AB6F0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2375 000059B6 0000                <1>
  2376 000059B8 E91EE1FFFF          <1> 	jmp	error
  2377                              <1> 
  2378                              <1> getspl: ; / get device number from a special file name
  2379 000059BD E81AF0FFFF          <1> 	call	namei
  2380                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2381                              <1> 		       ; ax = 0 -> file not found 	
  2382                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2383                              <1> 	; 04/02/2022
  2384 000059C2 7305                <1> 	jnc	short getspl_0
  2385 000059C4 E9C5FEFFFF          <1> 	jmp	sysmnt_err2
  2386                              <1> getspl_0:
  2387                              <1> 	;jz	error
  2388                              <1> 	;jc	error
  2389                              <1> 		; jsr r0,namei / get the i-number of the special file
  2390                              <1>                 ; br errora / no such file
  2391 000059C9 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2392                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2393                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2394 000059CD 72DF                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2395                              <1> 	;jc	error
  2396                              <1> 		; ble errora / less than 0?  yes, error
  2397 000059CF 6683F805            <1>         cmp	ax, 5 ;
  2398                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2399                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2400                              <1> 	;;ja	error
  2401                              <1>         ;	; bgt errora / yes, error
  2402                              <1>         ; 04/02/2022
  2403 000059D3 7600                <1> 	jna	short getspl_retn
  2404                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2405                              <1> ;iopen_retn:
  2406                              <1> ;	retn
  2407                              <1> 		; rts r0 / return with device number in r1
  2408                              <1> ;sysmnt_err0:
  2409                              <1> ;	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2410                              <1> ;	jmp	error
  2411                              <1> 
  2412                              <1> getspl_retn:
  2413                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2414                              <1> 	; 04/02/2022
  2415                              <1> iopen_retn:
  2416 000059D5 C3                  <1> 	retn
  2417                              <1> 
  2418                              <1> iopen:
  2419                              <1> 	; 04/02/2022
  2420                              <1> 	; 19/05/2015
  2421                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2422                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2423                              <1> 	;
  2424                              <1> 	; open file whose i-number is in r1
  2425                              <1> 	; 
  2426                              <1> 	; INPUTS ->
  2427                              <1> 	;    r1 - inode number
  2428                              <1> 	; OUTPUTS ->
  2429                              <1> 	;    file's inode in core	
  2430                              <1> 	;    r1 - inode number (positive)
  2431                              <1> 	;
  2432                              <1> 	; ((AX = R1))
  2433                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2434                              <1> 	;        
  2435                              <1> ; / open file whose i-number is in r1
  2436 000059D6 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2437                              <1> 		; tst r1 / write or read access?
  2438 000059D9 7568                <1>         jnz	short iopen_2
  2439                              <1> 		; blt 2f / write, go to 2f
  2440 000059DB B202                <1> 	mov	dl, 2 ; read access
  2441 000059DD E8E3F8FFFF          <1> 	call	access
  2442                              <1>         	; jsr r0,access; 2 
  2443                              <1> 	; / get inode into core with read access
  2444                              <1> 	; DL=2
  2445                              <1> iopen_0:
  2446 000059E2 6683F828            <1>         cmp	ax, 40
  2447                              <1> 		; cmp r1,$40. / is it a special file
  2448 000059E6 77ED                <1>         ja	short iopen_retn
  2449                              <1> 		; bgt 3f / no. 3f
  2450                              <1> 	; 04/02/2022
  2451 000059E8 50                  <1> 	push	eax
  2452                              <1> 	;push	ax
  2453                              <1> 		; mov r1,-(sp) / yes, figure out
  2454 000059E9 0FB6D8              <1> 	movzx	ebx, al
  2455 000059EC C0E302              <1> 	shl	bl, 2 ; * 4 ; 04/02/2022
  2456                              <1> 	;shl	bx, 2
  2457                              <1> 		; asl r1
  2458 000059EF 81C3[F3590000]      <1>         add     ebx, iopen_1 - 4
  2459 000059F5 FF23                <1> 	jmp	dword [ebx]
  2460                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2461                              <1> iopen_1: ; 1:
  2462 000059F7 [5B5A0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2463                              <1>  		 ;otty / tty ; r1=2
  2464                              <1>         	 ;oppt / ppt ; r1=4
  2465 000059FB [135B0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2466                              <1> 		 ;sret / mem ; r1=6
  2467                              <1> 		 ;sret / rf0
  2468                              <1>         	 ;sret / rk0
  2469                              <1>         	 ;sret / tap0
  2470                              <1>         	 ;sret / tap1
  2471                              <1>         	 ;sret / tap2
  2472                              <1>         	 ;sret / tap3
  2473                              <1>         	 ;sret / tap4
  2474                              <1>         	 ;sret / tap5
  2475                              <1>         	 ;sret / tap6
  2476                              <1>         	 ;sret / tap7
  2477 000059FF [135B0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2478 00005A03 [135B0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2479 00005A07 [135B0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2480 00005A0B [135B0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2481 00005A0F [135B0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2482 00005A13 [135B0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2483                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2484 00005A17 [135B0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2485 00005A1B [6C5A0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2486                              <1> 		 ;ocvt / tty0
  2487 00005A1F [6C5A0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2488                              <1> 		 ;ocvt / tty1
  2489 00005A23 [6C5A0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2490                              <1> 		 ;ocvt / tty2
  2491 00005A27 [6C5A0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2492                              <1> 		 ;ocvt / tty3
  2493 00005A2B [6C5A0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2494                              <1> 		 ;ocvt / tty4
  2495 00005A2F [6C5A0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2496                              <1> 		 ;ocvt / tty5
  2497 00005A33 [6C5A0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2498                              <1> 		 ;ocvt / tty6
  2499 00005A37 [6C5A0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2500                              <1> 		 ;ocvt / tty7
  2501 00005A3B [6C5A0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2502                              <1> 		 ;error / crd
  2503 00005A3F [6C5A0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2504                              <1> 
  2505                              <1> iopen_2: ; 2: / check open write access
  2506 00005A43 66F7D8              <1> 	neg	ax
  2507                              <1> 		; neg r1 / make inode number positive
  2508 00005A46 B201                <1> 	mov	dl, 1 ; write access
  2509 00005A48 E878F8FFFF          <1> 	call	access
  2510                              <1> 		; jsr r0,access; 1 / get inode in core
  2511                              <1> 	; DL=1
  2512                              <1> 	; 04/02/2022
  2513 00005A4D F605[596C0000]40    <1> 	test	byte [i.flgs+1], 40h
  2514                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2515                              <1>  		; bit $40000,i.flgs / is it a directory?
  2516 00005A54 748C                <1> 	jz	short iopen_0
  2517                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2518                              <1> 	;jmp	error ; permission denied !
  2519 00005A56 E953FFFFFF          <1> 	jmp	sysmnt_err0
  2520                              <1> 	;;jnz	error		
  2521                              <1>        		; bne 2f / yes, transfer (error)
  2522                              <1>         ;;jmp	short iopen_0
  2523                              <1> 	;cmp	ax, 40
  2524                              <1> 		; cmp r1,$40. / no, is it a special file?
  2525                              <1>         ;ja	short iopen_2
  2526                              <1> 		; bgt 3f / no, return
  2527                              <1> 	;push	ax
  2528                              <1> 		; mov r1,-(sp) / yes
  2529                              <1> 	;movzx	ebx, al
  2530                              <1> 	;shl	bx, 1
  2531                              <1> 		; asl r1
  2532                              <1> 	;add	ebx, ipen_3 - 2
  2533                              <1> 	;jmp	dword [ebx]
  2534                              <1> 		; jmp *1f-2(r1) / figure out 
  2535                              <1> 			; / which special file it is and transfer
  2536                              <1> ;iopen_3: ; 1:
  2537                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2538                              <1>  		 ;otty / tty ; r1=2
  2539                              <1>         	 ;leadr / ppt ; r1=4
  2540                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2541                              <1> 		 ;sret / mem ; r1=6
  2542                              <1> 		 ;sret / rf0
  2543                              <1>         	 ;sret / rk0
  2544                              <1>         	 ;sret / tap0
  2545                              <1>         	 ;sret / tap1
  2546                              <1>         	 ;sret / tap2
  2547                              <1>         	 ;sret / tap3
  2548                              <1>         	 ;sret / tap4
  2549                              <1>         	 ;sret / tap5
  2550                              <1>         	 ;sret / tap6
  2551                              <1>         	 ;sret / tap7
  2552                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2553                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2554                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2555                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2556                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2557                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2558                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2559                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2560                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2561                              <1> 		 ;ocvt / tty0
  2562                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2563                              <1> 		 ;ocvt / tty1
  2564                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2565                              <1> 		 ;ocvt / tty2
  2566                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2567                              <1> 		 ;ocvt / tty3
  2568                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2569                              <1> 		 ;ocvt / tty4
  2570                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2571                              <1> 		 ;ocvt / tty5
  2572                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2573                              <1> 		 ;ocvt / tty6
  2574                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2575                              <1> 		 ;ocvt / tty7
  2576                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2577                              <1> 		 ;/ ejec / lpr
  2578                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2579                              <1> 
  2580                              <1> otty: ;/ open console tty for reading or writing
  2581                              <1> 	; 03/03/2022
  2582                              <1> 	; 02/03/2022
  2583                              <1> 	; 27/02/2022
  2584                              <1> 	; 23/02/2022
  2585                              <1> 	; 22/02/2022
  2586                              <1> 	; 04/02/2022
  2587                              <1> 	; 16/11/2015
  2588                              <1> 	; 12/11/2015
  2589                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2590                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2591                              <1> 	; 16/07/2013
  2592                              <1> 	; Retro UNIX 8086 v1 modification:
  2593                              <1> 	;  If a tty is open for read or write by
  2594                              <1> 	;     a process (u.uno), only same process can open
  2595                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2596                              <1> 	;
  2597                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2598                              <1> 	;
  2599 00005A5B 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2600 00005A62 8A83[B76C0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2601                              <1> 	; 13/01/2014
  2602                              <1> 	;jmp	short ottyp
  2603                              <1> 	; 23/02/2022
  2604 00005A68 88C4                <1> 	mov	ah, al
  2605 00005A6A EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2606                              <1> ocvt:
  2607 00005A6C 2C0A                <1> 	sub	al, 10
  2608                              <1> 	; 04/02/2022
  2609 00005A6E 31DB                <1> 	xor	ebx, ebx
  2610                              <1> ottyp:
  2611                              <1> 	; 23/02/2022
  2612 00005A70 B4FF                <1> 	mov	ah, 0FFh
  2613                              <1> ottypc:
  2614                              <1> 	; 03/03/2022
  2615                              <1> 	; 23/02/2022
  2616                              <1> 	; 22/02/2022
  2617                              <1> 	; 12/02/2022
  2618                              <1> 	; 04/02/2022
  2619                              <1> 	; 16/11/2015
  2620                              <1> 	; 12/11/2015
  2621                              <1> 	; 18/05/2015 (32 bit modifications)
  2622                              <1> 	; 06/12/2013 - 13/07/2014
  2623 00005A72 88C6                <1> 	mov	dh, al ; tty number
  2624                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2625                              <1> 	; 04/02/2022
  2626 00005A74 88C3                <1> 	mov	bl, al
  2627 00005A76 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2628                              <1> 	; 26/01/2014	
  2629 00005A78 81C3[E46B0000]      <1> 	add 	ebx, ttyl
  2630 00005A7E 668B0B              <1> 	mov 	cx, [ebx]
  2631                              <1> 		   ; CL = lock value (0 or process number)
  2632                              <1> 		   ; CH = open count 
  2633 00005A81 20C9                <1> 	and 	cl, cl
  2634                              <1> 	; 13/01/2014
  2635                              <1> 	;jz 	short otty_ret
  2636                              <1> 	; 04/02/2022
  2637 00005A83 7447                <1> 	jz 	short ottys_0
  2638                              <1> 	;
  2639                              <1> 	; 16/11/2015
  2640 00005A85 3A0D[A56F0000]      <1> 	cmp 	cl, [u.uno]
  2641 00005A8B 746E                <1> 	je	short ottys_3
  2642                              <1> 	;
  2643                              <1> 	; 23/02/2022
  2644                              <1> 	; (is it the console tty of the current process?)
  2645                              <1> 	; ((fast check/permit for console tty open function))
  2646 00005A8D 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2647 00005A8F 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2648                              <1> 	;
  2649                              <1> 	; 22/02/2022
  2650                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2651                              <1> 	;shl 	bl, 1
  2652                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2653                              <1> 	;;movzx ebx, byte [u.uno]
  2654                              <1> 	;mov	bl, [u.uno]
  2655                              <1> 	;shl 	bl, 1
  2656                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2657                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2658                              <1> 	; 22/02/2022 (BugFix) ; *
  2659 00005A91 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2660 00005A94 D1E6                <1> 	shl 	esi, 1
  2661 00005A96 668B86[766C0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2662 00005A9D 96                  <1> 	xchg	esi, eax
  2663 00005A9E A0[A56F0000]        <1> 	mov	al, [u.uno]
  2664 00005AA3 D0E0                <1> 	shl 	al, 1
  2665 00005AA5 663BB0[966C0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2666 00005AAC 744D                <1> 	je 	short ottys_3 ; *
  2667                              <1> 	; 23/02/2022
  2668                              <1> 	; check console tty of the process
  2669                              <1> 	; (open permission must be given if the -requested- tty is
  2670                              <1> 	;  console tty of current process)
  2671 00005AAE D0E8                <1> 	shr	al, 1
  2672 00005AB0 38B0[B76C0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2673 00005AB6 7443                <1> 	je 	short ottys_3
  2674                              <1> 	;
  2675                              <1> 	; the tty is locked by another process
  2676                              <1> 	; except the parent process (p.ppid)
  2677                              <1>         ;
  2678                              <1> 	; 09/02/2022
  2679                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2680                              <1> 	;		; permission denied ! error
  2681                              <1> otty_err: ; 13/01/2014
  2682                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2683                              <1> 	;;jnz	error
  2684                              <1> 	; 04/02/2022
  2685                              <1> 	;jz	short otty_stc_retn
  2686                              <1> 	;jmp	error
  2687                              <1> 	; 12/02/2022
  2688 00005AB8 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2689 00005ABB 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2690                              <1> 	; iopen (dl=1 or dl=2)
  2691 00005ABD C705[AB6F0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2691 00005AC5 0000                <1>
  2692                              <1> 			; permission denied ! error
  2693 00005AC7 E90FE0FFFF          <1> 	jmp	error
  2694                              <1> ;otty_stc_retn:
  2695                              <1> 	;stc
  2696                              <1> 	;retn
  2697                              <1> ottys_0:
  2698                              <1> 	; 04/02/2022
  2699                              <1> otty_ret: 
  2700                              <1> 	; 13/01/2014
  2701 00005ACC 80FE07              <1> 	cmp 	dh, 7
  2702 00005ACF 7624                <1> 	jna	short ottys_2
  2703                              <1> 	; 16/11/2015
  2704                              <1> com_port_check:
  2705 00005AD1 BE[026C0000]        <1> 	mov	esi, com1p
  2706 00005AD6 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2707 00005AD9 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2708 00005ADB 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2709                              <1> ottys_1:
  2710                              <1> 	; 12/11/2015
  2711 00005ADC 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2712 00005ADF 7714                <1> 	ja	short com_port_ready
  2713                              <1> 	;
  2714                              <1> 	; 12/02/2022
  2715 00005AE1 80FA01              <1> 	cmp	dl, 1	; dl = 0 ?
  2716 00005AE4 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2717 00005AE6 C705[AB6F0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2717 00005AEE 0000                <1>
  2718                              <1> 			   ; device not ready ! error
  2719                              <1> 	;jmp	short otty_err
  2720 00005AF0 E9E6DFFFFF          <1> 	jmp	error
  2721                              <1> com_port_ready:
  2722                              <1> ottys_2:
  2723                              <1> 	; 02/03/2022
  2724                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2725                              <1> 	;jnz	short ottys_3
  2726 00005AF5 8A0D[A56F0000]      <1> 	mov	cl, [u.uno]
  2727                              <1> ottys_3:
  2728 00005AFB FEC5                <1> 	inc 	ch
  2729 00005AFD 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2730                              <1> 	; 06/12/2013
  2731 00005B00 FEC6                <1> 	inc	dh	; tty number + 1
  2732 00005B02 BB[8C6F0000]        <1> 	mov	ebx, u.ttyp
  2733                              <1> 	; 13/01/2014
  2734 00005B07 F6C202              <1> 	test	dl, 2	; open for read sign
  2735 00005B0A 7501                <1> 	jnz	short ottys_4
  2736 00005B0C 43                  <1> 	inc	ebx
  2737                              <1> ottys_4:
  2738                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2739 00005B0D 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2740                              <1> 	; 27/02/2022
  2741 00005B0F 08D2                <1> 	or	dl, dl	; sysstty system call check (DL=0)
  2742 00005B11 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2743                              <1> sret:
  2744                              <1> 	;pop 	ax
  2745                              <1> 	; 04/02/2022
  2746 00005B13 58                  <1> 	pop	eax
  2747                              <1> otty_retn:	; 12/02/2022
  2748                              <1> iclose_retn:	
  2749 00005B14 C3                  <1> 	retn
  2750                              <1> 
  2751                              <1> 	;
  2752                              <1> 	; Original UNIX v1 'otty' routine:
  2753                              <1> 	;	
  2754                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2755                              <1>         ;                 / reader status reg
  2756                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2757                              <1>         ;                 / punch status reg
  2758                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2759                              <1>         ;                          / console tty buffer
  2760                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2761                              <1>         ;            / console tty
  2762                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2763                              <1>         ;             / buffer header
  2764                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2765                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2766                              <1>         ;                 / tty
  2767                              <1>         ;br     sret / ?
  2768                              <1> ;sret:
  2769                              <1> 		; clr *$ps / set processor priority to zero
  2770                              <1> ;	pop	ax
  2771                              <1>         	; mov (sp)+,r1 / pop stack to r1
  2772                              <1> ;3:
  2773                              <1> ;	retn
  2774                              <1>         	; rts r0
  2775                              <1> 	
  2776                              <1> ;ocvt:	; < open tty >
  2777                              <1> 	; 13/01/2014
  2778                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2779                              <1> 	; 24/09/2013 consistency check -> ok
  2780                              <1> 	; 16/09/2013
  2781                              <1> 	; 03/09/2013
  2782                              <1> 	; 27/08/2013
  2783                              <1> 	; 16/08/2013
  2784                              <1> 	; 16/07/2013
  2785                              <1> 	; 27/05/2013
  2786                              <1> 	; 21/05/2013
  2787                              <1> 	;
  2788                              <1> 	; Retro UNIX 8086 v1 modification !
  2789                              <1> 	; 
  2790                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2791                              <1> 	;		(exactly different than this one)
  2792                              <1> 	;	was in 'u9.s' file.
  2793                              <1> 	;
  2794                              <1> 	; 16/07/2013
  2795                              <1> 	; Retro UNIX 8086 v1 modification:
  2796                              <1> 	;  If a tty is open for read or write by
  2797                              <1> 	;     a process (u.uno), only same process can open
  2798                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2799                              <1> 	;
  2800                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2801                              <1> 
  2802                              <1> 	; 16/09/2013
  2803                              <1> 	; sub 	al, 10
  2804                              <1> 	
  2805                              <1> 	; 06/12/2013
  2806                              <1> 	;cmp	al, 7
  2807                              <1>         ;jna     short ottyp
  2808                              <1> 	; 13/01/2014
  2809                              <1> 	;jmp	short ottyp
  2810                              <1> 
  2811                              <1> 
  2812                              <1> ;oppt: / open paper tape for reading or writing
  2813                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2814                              <1> ;        tstb   pptiflg / is file already open
  2815                              <1> ;        bne    2f / yes, branch
  2816                              <1> ;1:
  2817                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2818                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2819                              <1> ;               br .+4 / for paper tape input and place in free list
  2820                              <1> ;        br     1b
  2821                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2822                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2823                              <1> ;        br     sret
  2824                              <1> ;2:
  2825                              <1> ;        jmp    error / file already open
  2826                              <1> 
  2827                              <1> iclose: 
  2828                              <1> 	; 04/02/2022
  2829                              <1> 	; 19/05/2015
  2830                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2831                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2832                              <1> 	;
  2833                              <1> 	; close file whose i-number is in r1
  2834                              <1> 	; 
  2835                              <1> 	; INPUTS ->
  2836                              <1> 	;    r1 - inode number
  2837                              <1> 	; OUTPUTS ->
  2838                              <1> 	;    file's inode in core	
  2839                              <1> 	;    r1 - inode number (positive)
  2840                              <1> 	;
  2841                              <1> 	; ((AX = R1))
  2842                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2843                              <1> 	;        
  2844                              <1> ;/ close file whose i-number is in r1
  2845 00005B15 B202                <1> 	mov	dl, 2 ; 12/01/2014
  2846 00005B17 F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2847                              <1> 		; tst r1 / test i-number
  2848                              <1>         ;jnz	short iclose_2
  2849                              <1> 		; blt 2f / if neg., branch
  2850 00005B1A 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2851                              <1> 	; 16/07/2013 
  2852 00005B1C 66F7D8              <1> 	neg	ax ; make it positive
  2853                              <1> 	; 12/01/2014
  2854 00005B1F FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2855                              <1> iclose_0:
  2856 00005B21 6683F828            <1> 	cmp	ax, 40
  2857                              <1> 		; cmp r1,$40. / is it a special file
  2858 00005B25 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2859                              <1> 		; bgt 3b / no, return
  2860                              <1> 	; 12/01/2014
  2861                              <1> 	; DL=2 -> special file was opened for reading
  2862                              <1> 	; DL=1 -> special file was opened for writing
  2863                              <1> 	; 04/02/2022
  2864 00005B27 50                  <1> 	push	eax
  2865                              <1> 	;push	ax
  2866                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2867 00005B28 0FB6D8              <1> 	movzx	ebx, al
  2868                              <1> 	; 04/02/2022
  2869 00005B2B C0E302              <1> 	shl	bl, 2
  2870                              <1> 	;shl	bx, 2
  2871                              <1> 		; asl r1
  2872 00005B2E 81C3[325B0000]      <1> 	add	ebx, iclose_1 - 4
  2873 00005B34 FF23                <1> 	jmp	dword [ebx]
  2874                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2875                              <1> iclose_1 :
  2876 00005B36 [825B0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2877 00005B3A [DD5B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2878 00005B3E [DD5B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2879 00005B42 [DD5B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2880 00005B46 [DD5B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2881 00005B4A [DD5B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2882 00005B4E [DD5B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2883 00005B52 [DD5B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2884 00005B56 [DD5B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2885                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2886                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2887 00005B5A [915B0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2888 00005B5E [915B0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2889 00005B62 [915B0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2890 00005B66 [915B0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2891 00005B6A [915B0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2892 00005B6E [915B0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2893 00005B72 [915B0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2894 00005B76 [915B0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2895 00005B7A [915B0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2896 00005B7E [915B0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2897                              <1> 
  2898                              <1> 	; 1:
  2899                              <1> 	;        ctty   / tty
  2900                              <1> 	;        cppt   / ppt
  2901                              <1> 	;        sret   / mem
  2902                              <1> 	;        sret   / rf0
  2903                              <1> 	;        sret   / rk0
  2904                              <1> 	;        sret   / tap0
  2905                              <1> 	;        sret   / tap1
  2906                              <1> 	;        sret   / tap2
  2907                              <1> 	;        sret   / tap3
  2908                              <1> 	;        sret   / tap4
  2909                              <1> 	;        sret   / tap5
  2910                              <1> 	;        sret   / tap6
  2911                              <1> 	;        sret   / tap7
  2912                              <1> 	;        ccvt   / tty0
  2913                              <1> 	;        ccvt   / tty1
  2914                              <1> 	;        ccvt   / tty2
  2915                              <1> 	;        ccvt   / tty3
  2916                              <1> 	;        ccvt   / tty4
  2917                              <1> 	;        ccvt   / tty5
  2918                              <1> 	;        ccvt   / tty6
  2919                              <1> 	;        ccvt   / tty7
  2920                              <1> 	;        error / crd
  2921                              <1> 
  2922                              <1> ;iclose_2: ; 2: / negative i-number
  2923                              <1> 	;neg	ax
  2924                              <1> 		;neg r1 / make it positive
  2925                              <1> 	;cmp	ax, 40
  2926                              <1> 		;cmp r1,$40. / is it a special file?
  2927                              <1>         ;ja	short @b
  2928                              <1> 		;bgt    3b / no. return
  2929                              <1> 	;push	ax
  2930                              <1> 		;mov r1,-(sp)
  2931                              <1> 	;movzx	ebx, al
  2932                              <1> 	;shl	bx, 1
  2933                              <1> 		;asl r1 / yes. compute jump address and transfer
  2934                              <1> 	;add	ebx, iclose_3 - 2
  2935                              <1> 	;jmp	dword [ebx]
  2936                              <1> 		;jmp *1f-2(r1) / figure out 
  2937                              <1> ;iclose_3:
  2938                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2939                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2940                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2941                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2942                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2943                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2944                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2945                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2946                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2947                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2948                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2949                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2950                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2951                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2952                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2953                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2954                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2955                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2956                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2957                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2958                              <1> 	
  2959                              <1> 	;1:
  2960                              <1> 	;      	ctty   / tty
  2961                              <1> 	;       leadr  / ppt
  2962                              <1> 	;       sret   / mem
  2963                              <1> 	;       sret   / rf0
  2964                              <1> 	;       sret   / rk0
  2965                              <1> 	;       sret   / tap0
  2966                              <1> 	;       sret   / tap1
  2967                              <1> 	;       sret   / tap2
  2968                              <1> 	;       sret   / tap3
  2969                              <1> 	;       sret   / tap4
  2970                              <1> 	;       sret   / tap5
  2971                              <1> 	;       sret   / tap6
  2972                              <1> 	;       sret   / tap7
  2973                              <1> 	;       ccvt   / tty0
  2974                              <1> 	;       ccvt   / tty1
  2975                              <1> 	;       ccvt   / tty2
  2976                              <1> 	;       ccvt   / tty3
  2977                              <1> 	;       ccvt   / tty4
  2978                              <1> 	;       ccvt   / tty5
  2979                              <1> 	;       ccvt   / tty6
  2980                              <1> 	;       ccvt   / tty7
  2981                              <1> 	;/       ejec / lpr
  2982                              <1> 
  2983                              <1> ctty: ; / close console tty
  2984                              <1> 	; 25/02/2022
  2985                              <1> 	; 12/02/2022
  2986                              <1> 	; 05/02/2022
  2987                              <1> 	; 04/02/2022
  2988                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2989                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2990                              <1> 	;
  2991                              <1> 	; Retro UNIX 8086 v1 modification !
  2992                              <1> 	; (DL = 2 -> it is open for reading)
  2993                              <1> 	; (DL = 1 -> it is open for writing)
  2994                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2995                              <1> 	;
  2996                              <1> 	; 06/12/2013
  2997 00005B82 0FB61D[A56F0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2998 00005B89 8A83[B76C0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2999                              <1> 	; 13/01/2014
  3000                              <1> 	;jmp	short cttyp
  3001                              <1> 	; 05/02/2022
  3002 00005B8F EB04                <1> 	jmp	short ctty_0
  3003                              <1> ccvt:
  3004 00005B91 2C0A                <1> 	sub 	al, 10
  3005                              <1> cttyp:	; (call from sysstty)
  3006                              <1> 	; 08/01/2022
  3007 00005B93 31DB                <1> 	xor	ebx, ebx
  3008                              <1> ctty_0:	
  3009                              <1> 	; 18/05/2015 (32 bit modifications)
  3010                              <1> 	; 16/08/2013 - 26/01/2014
  3011                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  3012                              <1> 	; 04/02/2022
  3013 00005B95 88C3                <1> 	mov	bl, al
  3014 00005B97 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  3015                              <1> 	; 26/01/2014
  3016 00005B99 81C3[E46B0000]      <1> 	add 	ebx, ttyl
  3017 00005B9F 88C6                <1> 	mov 	dh, al ; tty number
  3018 00005BA1 668B03              <1> 	mov 	ax, [ebx]
  3019                              <1> 		   ; AL = lock value (0 or process number)
  3020                              <1> 		   ; AH = open count 
  3021 00005BA4 20E4                <1> 	and 	ah, ah
  3022 00005BA6 7514                <1> 	jnz	short ctty_ret
  3023                              <1>   	; 12/02/2022
  3024 00005BA8 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3025 00005BAB 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3026                              <1> 	; iclose (dl=1 or dl=2)
  3027 00005BAD C705[AB6F0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3027 00005BB5 0000                <1>
  3028                              <1> 			; device not open ! error
  3029                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3030 00005BB7 E91FDFFFFF          <1> 	jmp	error
  3031                              <1> 	; 26/01/2014
  3032                              <1> ctty_ret:
  3033 00005BBC FECC                <1> 	dec 	ah ; decrease open count
  3034 00005BBE 7502                <1> 	jnz	short ctty_1
  3035 00005BC0 30C0                <1> 	xor	al, al ; unlock/free tty
  3036                              <1> ctty_1:
  3037 00005BC2 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3038                              <1> 	;
  3039 00005BC5 BB[8C6F0000]        <1> 	mov	ebx, u.ttyp
  3040                              <1> 	;test	dl, 1 ; open for write sign
  3041                              <1> 	;jz	short ctty_2
  3042                              <1> 	; 25/02/2022
  3043 00005BCA F6C202              <1> 	test	dl, 2 ; open for read sign
  3044 00005BCD 7501                <1> 	jnz	short ctty_2
  3045 00005BCF 43                  <1> 	inc	ebx
  3046                              <1> ctty_2:
  3047 00005BD0 FEC6                <1> 	inc	dh ; tty number + 1
  3048 00005BD2 3A33                <1> 	cmp	dh, [ebx]
  3049                              <1> 	;jne	short cret
  3050 00005BD4 7503                <1> 	jne	short ctty_3 ; 12/02/2022
  3051                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3052 00005BD6 C60300              <1> 	mov	byte [ebx], 0
  3053                              <1> ctty_3:
  3054                              <1> 	; 12/02/2022
  3055 00005BD9 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3056 00005BDB 7401                <1> 	jz	short ctty_4
  3057                              <1> cret:
  3058                              <1> 	;pop	ax
  3059                              <1> 	; 05/02/2022
  3060 00005BDD 58                  <1> 	pop	eax
  3061                              <1> ctty_stc_retn:	; 12/02/2022
  3062                              <1> ctty_4:
  3063 00005BDE C3                  <1> 	retn
  3064                              <1> 
  3065                              <1> ;ctty_err: ; 13/01/2014
  3066                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3067                              <1> ;	jnz	error
  3068                              <1> ;	stc
  3069                              <1> ;	retn
  3070                              <1> 
  3071                              <1> 	; Original UNIX v1 'ctty' routine:
  3072                              <1> 	;	
  3073                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3074                              <1> 	;		;/ point r5 to the console tty buffer
  3075                              <1>         ;decb   (r5) / dec number of processes using console tty
  3076                              <1>         ;br     sret / return via sret
  3077                              <1> 
  3078                              <1> ;ccvt:	; < close tty >
  3079                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3080                              <1> 	;
  3081                              <1> 	; Retro UNIX 8086 v1 modification !
  3082                              <1> 	; 
  3083                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3084                              <1> 	;		(exactly different than this one)
  3085                              <1> 	;	was in 'u9.s' file.
  3086                              <1> 	;
  3087                              <1> 	; DL = 2 -> it is open for reading
  3088                              <1> 	; DL = 1 -> it is open for writing
  3089                              <1> 	;
  3090                              <1> 	; 17/09/2013
  3091                              <1> 	;sub 	al, 10
  3092                              <1> 	;cmp	al, 7
  3093                              <1> 	;jna	short cttyp
  3094                              <1> 	; 13/01/2014
  3095                              <1> 	;jmp	short cttyp
  3096                              <1> 
  3097                              <1> ;cppt: / close paper tape
  3098                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3099                              <1> ;1:
  3100                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3101                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3102                              <1> ;                          / and assign to free list
  3103                              <1> ;               br sret
  3104                              <1> ;        br     1b
  3105                              <1> 
  3106                              <1> ;ejec:	
  3107                              <1> ;	jmp	error
  3108                              <1> ;/ejec:
  3109                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3110                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3111                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3112                              <1> ;/       br     sret / return to caller via 'sret'
  2054                                  %include 'u8.s'        ; 11/06/2015
  2055                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2056                              <1> ; Last Modification: 12/02/2022
  2057                              <1> ; ----------------------------------------------------------------------------
  2058                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2059                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2060                              <1> ;
  2061                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2062                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2063                              <1> ; <Bell Laboratories (17/3/1972)>
  2064                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2065                              <1> ;
  2066                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2067                              <1> ;
  2068                              <1> ; ****************************************************************************
  2069                              <1> ; 24/10/2015
  2070                              <1> 
  2071                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2072                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2073                              <1> ;; Word 1, byte 0 = device id
  2074                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2075                              <1> ;;          bit 9 = write bit
  2076                              <1> ;;	    bit 10 = read bit	  
  2077                              <1> ;;	    bit 12 = waiting to write bit	
  2078                              <1> ;;	    bit 13 = waiting to read bit
  2079                              <1> ;;	    bit 15 = inhibit bit
  2080                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2081                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2082                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2083                              <1> ;;
  2084                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2085                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2086                              <1> ;;
  2087                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2088                              <1> ;; Word 1, Byte 0 = device id
  2089                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2090                              <1> ;;          bit 9 = write bit
  2091                              <1> ;;	    bit 10 = read bit	  
  2092                              <1> ;;	    bit 12 = waiting to write bit	
  2093                              <1> ;;	    bit 13 = waiting to read bit
  2094                              <1> ;;	    bit 15 = inhibit bit
  2095                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2096                              <1> ;;
  2097                              <1> ;; Original UNIX v1 ->
  2098                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2099                              <1> ;; Original UNIX v1 -> 
  2100                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2101                              <1> ;;
  2102                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2103                              <1> ;;
  2104                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2105                              <1> ;;          0 = fd0
  2106                              <1> ;;	    1 = fd1
  2107                              <1> ;;	    2 = hd0
  2108                              <1> ;;	    3 = hd1
  2109                              <1> ;;	    4 = hd2
  2110                              <1> ;;	    5 = hd3
  2111                              <1> 
  2112                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2113                              <1> 
  2114                              <1> 	; 04/02/2022
  2115                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2116                              <1> 	; 26/04/2013
  2117                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2118                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2119                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2120                              <1> 
  2121                              <1> 	; 04/02/2022
  2122                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2123                              <1> 	; 26/04/2013
  2124                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2125                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2126                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2127                              <1> 
  2128                              <1> bread: 
  2129                              <1> 	; 12/02/2022
  2130                              <1> 	; 04/02/2022
  2131                              <1> 	; 14/07/2015
  2132                              <1> 	; 10/07/2015
  2133                              <1> 	; 09/06/2015
  2134                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2135                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2136                              <1> 	;	
  2137                              <1> 	; / read a block from a block structured device
  2138                              <1> 	;
  2139                              <1> 	; INPUTS ->
  2140                              <1> 	;    [u.fofp] points to the block number
  2141                              <1> 	;    CX = maximum block number allowed on device
  2142                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2143                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2144                              <1> 	;    [u.count]	number of bytes to read in
  2145                              <1> 	; OUTPUTS ->
  2146                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2147                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2148                              <1> 	;
  2149                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2150                              <1> 	;
  2151                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2152                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2153                              <1> 	;	is increased by 1. For example: If user/program request 
  2154                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2155                              <1> 	;  	the next block number just as 512 byte reading is done.
  2156                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2157                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2158                              <1> 	;       enough to keep byte position/offset of the disk), this
  2159                              <1> 	;	defect will not be corrected, user/program must request
  2160                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2161                              <1> 	;       for achieving correct result. In future version(s), 
  2162                              <1> 	;	this defect will be corrected by using different 
  2163                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2164                              <1> 
  2165                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2166                              <1> 			       ; / (only works on tape)
  2167                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2168                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2169                              <1> ;1:
  2170                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2171                              <1> 			    ; / maximum block # allowed on device
  2172                              <1> 		; jnb short @f
  2173                              <1> 		; bhis	1f / yes, 1f (error)
  2174                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2175                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2176                              <1> 		; mov (sp)+,r1 / return block # to r1
  2177                              <1> 		; inc r1 / bump block # to next consecutive block
  2178                              <1> 		; dec (sp) / "2-1-cold" on stack
  2179                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2180                              <1> ;1:
  2181                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2182                              <1> 	;push	ecx ; **
  2183                              <1> 	;26/04/2013
  2184                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2185 00005BDF 2C03                <1> 	sub	al, 3
  2186                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2187 00005BE1 A2[BE6F0000]        <1> 	mov	[u.brwdev], al
  2188                              <1> 	; 09/06/2015
  2189                              <1> 	;movzx	ebx, al
  2190                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2191                              <1> 	; 04/02/2022 (BugFix)
  2192 00005BE6 C0E002              <1> 	shl	al, 2 ; * 4
  2193 00005BE9 8B88[BE660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2194                              <1> bread_0:
  2195 00005BEF 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2196                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2197                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2198 00005BF0 8B1D[6C6F0000]      <1> 	mov	ebx, [u.fofp]
  2199 00005BF6 8B03                <1> 	mov	eax, [ebx]
  2200 00005BF8 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2201                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2202                              <1> 			       ; / block #
  2203 00005BFB 39C8                <1> 	cmp	eax, ecx
  2204                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2205                              <1>        	                     ; / block number allowed
  2206                              <1> 	;jnb	error 	     ; 18/04/2013
  2207                              <1> 		; bhis error10 / yes, error
  2208                              <1> 	; 12/02/2022
  2209                              <1> 	;jb	short bread_1
  2210                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2211                              <1> 	;jmp	error
  2212 00005BFD 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2213                              <1> bread_1:
  2214                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2215                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2216                              <1> 	; eAX = Block number (zero based)
  2217                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2218                              <1> preread: ;; call preread
  2219 00005BFF BF[BE6F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2220 00005C04 E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2221                              <1> 	;; jc 	error
  2222                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2223                              <1>         ; eAX = Block/Sector number (r1)
  2224                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2225                              <1> 	; 14/03/2013
  2226 00005C09 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2227                              <1>        		; br 1f / branch if block already in a I/O buffer
  2228 00005C0B 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2229                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2230 00005C10 E8DA010000          <1> 	call	poke
  2231                              <1>         	; jsr r0,poke / perform the read
  2232                              <1> 	;;jc	error ;2 0/07/2013
  2233                              <1> ; 1:
  2234                              <1>  		; clr *$ps / ps = 0
  2235                              <1>         	; rts r0
  2236                              <1> 	; 12/02/2022
  2237 00005C15 7305                <1> 	jnc	short bread_2
  2238 00005C17 E937010000          <1> 	jmp	dskrd_err
  2239                              <1> 
  2240                              <1> ;; return from preread
  2241                              <1> bread_2:
  2242 00005C1C 66810B0040          <1> 	or	word [ebx], 4000h 
  2243                              <1> 		; bis $40000,(r5) 
  2244                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2245                              <1> bread_3: ; 1:
  2246 00005C21 66F7030024          <1> 	test	word [ebx], 2400h
  2247                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2248 00005C26 7407                <1> 	jz	short bread_4
  2249                              <1> 		; beq 1f / no
  2250                              <1> 		; cmp cdev,$1 / disk or drum?
  2251                              <1> 		; ble 2f / yes
  2252                              <1> 		; tstb uquant / is the time quantum = 0?
  2253                              <1> 		; bne 2f / no, 2f
  2254                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2255                              <1> 		; jsr r0,sleep; 31. 
  2256                              <1> 			; / put process to sleep in channel 31 (tape)
  2257                              <1> 		; mov (sp)+,r5 / restore r5
  2258                              <1> 		; br 1b / go back
  2259                              <1> ; 2: / drum or disk
  2260                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2261 00005C28 E856F3FFFF          <1> 	call	idle
  2262                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2263 00005C2D EBF2                <1> 	jmp	short bread_3
  2264                              <1>        		; br 1b
  2265                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2266 00005C2F 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2267                              <1> 		; bic $40000,(r5) / clear bit 14
  2268                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2269 00005C34 83C308              <1> 	add	ebx, 8
  2270                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2271                              <1> 	; 09/06/2015
  2272 00005C37 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0
  2273 00005C3F 7705                <1> 	ja	short bread_5
  2274 00005C41 E814F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2275                              <1> bread_5:
  2276                              <1> 	; eBX = system (I/O) buffer address
  2277 00005C46 E870000000          <1> 	call	dioreg
  2278                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2279                              <1> 	; esi = start address of the transfer (in the buffer)
  2280                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2281                              <1> 	; ecx = transfer count (in bytes)
  2282                              <1> 	;
  2283                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2284                              <1> ;   / of users data
  2285 00005C4B F3A4                <1> 	rep	movsb
  2286                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2287                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2288                              <1>        		; bne 1b
  2289 00005C4D 59                  <1> 	pop	ecx ; **
  2290 00005C4E 833D[806F0000]00    <1> 	cmp	dword [u.count], 0
  2291                              <1> 		; tst u.count / done
  2292 00005C55 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2293                              <1>        		; beq 1f / yes, return
  2294                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2295                              <1>        		; br bread / read some more
  2296                              <1> ; 1:
  2297 00005C57 58                  <1> 	pop	eax ; ****
  2298                              <1>        		; mov (sp)+,r0
  2299 00005C58 C3                  <1>         retn		; 09/06/2015
  2300                              <1> 	;jmp	ret_ 
  2301                              <1> 		;jmp ret / jump to routine that called readi
  2302                              <1> 
  2303                              <1> 	; 08/02/2022
  2304                              <1> brw_oov_err:
  2305 00005C59 C705[AB6F0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2305 00005C61 0000                <1>
  2306 00005C63 E973DEFFFF          <1> 	jmp	error
  2307                              <1> 
  2308                              <1> 	; 12/02/2022
  2309                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2310                              <1> 	; 26/04/2013
  2311                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2312                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2313                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2314                              <1> 
  2315                              <1> 	; 12/02/2022				
  2316                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2317                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2318                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2319                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2320                              <1> 
  2321                              <1> bwrite: 
  2322                              <1> 	; 12/02/2022
  2323                              <1> 	; 04/02/2022
  2324                              <1> 	; 14/07/2015
  2325                              <1> 	; 10/07/2015
  2326                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2327                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2328                              <1> 	;	
  2329                              <1> 	;; / write on block structured device
  2330                              <1> 	;
  2331                              <1> 	; INPUTS ->
  2332                              <1> 	;    [u.fofp] points to the block number
  2333                              <1> 	;    CX = maximum block number allowed on device
  2334                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2335                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2336                              <1> 	;    [u.count]	number of bytes to user desires to write
  2337                              <1> 	; OUTPUTS ->
  2338                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2339                              <1> 	;
  2340                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2341                              <1> 	;
  2342                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2343                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2344                              <1> 	;	is increased by 1. For example: If user/program request 
  2345                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2346                              <1> 	;  	the next block number just as 512 byte writing is done.
  2347                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2348                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2349                              <1> 	;       enough to keep byte position/offset of the disk), this
  2350                              <1> 	;	defect will not be corrected, user/program must request
  2351                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2352                              <1> 	;       for achieving correct result. In future version(s), 
  2353                              <1> 	;	this defect will be corrected by using different 
  2354                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2355                              <1> 
  2356                              <1>        		; jsr r0,tstdeve / test the device for an error
  2357                              <1> 	;push	ecx ; **
  2358                              <1> 	;26/04/2013
  2359                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2360 00005C68 2C03                <1> 	sub	al, 3
  2361                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2362 00005C6A A2[BE6F0000]        <1> 	mov	[u.brwdev], al
  2363                              <1> 	; 09/06/2015
  2364                              <1> 	;movzx	ebx, al
  2365                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2366                              <1> 	; 04/02/2022 (BugFix)
  2367 00005C6F C0E002              <1> 	shl	al, 2 ; * 4
  2368 00005C72 8B88[BE660000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2369                              <1> bwrite_0:
  2370 00005C78 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2371                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2372                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2373 00005C79 8B1D[6C6F0000]      <1> 	mov	ebx, [u.fofp]
  2374 00005C7F 8B03                <1> 	mov	eax, [ebx]       
  2375 00005C81 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2376                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2377 00005C84 39C8                <1> 	cmp	eax, ecx
  2378                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2379                              <1>        	                     ; / block number allowed
  2380                              <1> 	;jnb	error	     ; 18/04/2013
  2381                              <1> 		; bhis error10 / yes, error
  2382                              <1>      	; 12/02/2022
  2383                              <1> 	;jb	short bwrite_1
  2384                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2385                              <1> 	;jmp	error
  2386 00005C86 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2387                              <1> bwrite_1:
  2388                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2389                              <1> 		; inc *u.fofp / no, increment block number
  2390                              <1> 	; 09/06/2015 - 10/07/2015
  2391 00005C88 66833D[BB6F0000]00  <1> 	cmp	word [u.pcount], 0
  2392 00005C90 7705                <1> 	ja	short bwrite_2
  2393 00005C92 E8BFF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2394                              <1> bwrite_2:
  2395 00005C97 BF[BE6F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2396 00005C9C E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2397                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2398                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2399 00005CA1 E815000000          <1>         call	dioreg
  2400                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2401                              <1> 	; esi =  destination address (in the buffer)
  2402                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2403                              <1> 	; ecx =  transfer count (in bytes)
  2404                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2405 00005CA6 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2406 00005CA8 F3A4                <1> 	rep	movsb
  2407                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2408                              <1>        		; dec r3 / area to the I/O buffer
  2409                              <1>        		; bne 1b
  2410 00005CAA E80D010000          <1> 	call	dskwr
  2411                              <1> 		; jsr r0,dskwr / write it out on the device
  2412 00005CAF 59                  <1> 	pop	ecx ; **
  2413 00005CB0 833D[806F0000]00    <1>         cmp     dword [u.count], 0
  2414                              <1> 		; tst u.count / done
  2415 00005CB7 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2416                              <1> 		; beq 1f / yes, 1f
  2417                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2418                              <1>        		; br bwrite / go back and write next block
  2419                              <1> ; 1:
  2420 00005CB9 58                  <1> 	pop	eax ; ****
  2421                              <1>        		; mov (sp)+,r0
  2422 00005CBA C3                  <1> 	retn		; 09/06/2015
  2423                              <1>         ;jmp	ret_ 
  2424                              <1> 		; jmp ret / return to routine that called writei
  2425                              <1> ;error10:
  2426                              <1> ;       jmp     error  ; / see 'error' routine
  2427                              <1> 
  2428                              <1> dioreg:
  2429                              <1> 	; 04/02/2022
  2430                              <1> 	; 14/07/2015
  2431                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2432                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2433                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2434                              <1> 	;	
  2435                              <1> 	; bookkeeping on block transfers of data
  2436                              <1> 	;
  2437                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2438                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2439                              <1> 	; 10/07/2015
  2440                              <1> 	; * returns byte offset from beginning of current sector buffer
  2441                              <1> 	; (beginning of data) in ESI
  2442                              <1> 	;
  2443 00005CBB 8B0D[806F0000]      <1> 	mov	ecx, [u.count]
  2444                              <1> 		; mov u.count,r3 / move char count to r3
  2445                              <1>         ; 04/02/2022
  2446 00005CC1 31D2                <1> 	xor	edx, edx
  2447 00005CC3 B602                <1> 	mov	dh, 2
  2448                              <1> 	; edx = 512
  2449 00005CC5 39D1                <1> 	cmp	ecx, edx ; 512
  2450                              <1> 	;cmp 	ecx, 512
  2451                              <1> 		; cmp r3,$512. / more than 512. char?
  2452 00005CC7 7602                <1> 	jna	short dioreg_0
  2453                              <1> 		; blos 1f / no, branch
  2454 00005CC9 89D1                <1> 	mov	ecx, edx ; 512
  2455                              <1> 	;mov	ecx, 512
  2456                              <1> 		; mov $512.,r3 / yes, just take 512.
  2457                              <1> dioreg_0:
  2458                              <1> 	; 09/06/2015
  2459 00005CCB 663B0D[BB6F0000]    <1> 	cmp	cx, [u.pcount]
  2460 00005CD2 7607                <1> 	jna	short dioreg_1
  2461 00005CD4 668B0D[BB6F0000]    <1> 	mov	cx, [u.pcount]
  2462                              <1> dioreg_1:
  2463                              <1> ; 1:
  2464 00005CDB 8B15[7C6F0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2465                              <1> 	        ; mov u.base,r2 / put users base in r2
  2466 00005CE1 010D[846F0000]      <1> 	add	[u.nread], ecx
  2467                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2468 00005CE7 290D[806F0000]      <1> 	sub	[u.count], ecx
  2469                              <1> 		; sub r3,u.count / update count
  2470 00005CED 010D[7C6F0000]      <1> 	add	[u.base], ecx
  2471                              <1> 		; add r3,u.base / update base
  2472                              <1> 	; 10/07/2015
  2473                              <1> 	; Retro UNIX 386 v1 - modification !
  2474                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2475                              <1> 	; (It will point to next byte position instead of next block no.)
  2476 00005CF3 8B35[6C6F0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2477 00005CF9 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2478 00005CFB 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2479 00005CFD 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2480 00005D02 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2481 00005D04 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2482                              <1> 	; 09/06/2015 - 10/07/2015
  2483 00005D06 66290D[BB6F0000]    <1> 	sub	[u.pcount], cx
  2484 00005D0D 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2485 00005D13 8B3D[B76F0000]      <1> 	mov	edi, [u.pbase]
  2486 00005D19 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2487 00005D1F 01D7                <1> 	add	edi, edx
  2488 00005D21 893D[B76F0000]      <1> 	mov	[u.pbase], edi
  2489 00005D27 010D[B76F0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2490 00005D2D C3                  <1> 	retn
  2491                              <1> 		; rts r0 / return
  2492                              <1> 
  2493                              <1> dskrd:
  2494                              <1> 	; 12/02/2022
  2495                              <1> 	; 18/08/2015
  2496                              <1> 	; 02/07/2015
  2497                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2498                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2499                              <1> 	;
  2500                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2501                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2502                              <1> 	; (number specified in r1) in the acquired buffer.
  2503                              <1> 	; If the device is busy at the time dskrd is called,	
  2504                              <1> 	; dskrd calls idle.
  2505                              <1> 	; 
  2506                              <1> 	; INPUTS ->
  2507                              <1> 	;    r1 - block number
  2508                              <1> 	;    cdev - current device number 
  2509                              <1> 	; OUTPUTS ->
  2510                              <1> 	;    r5 - points to first data word in I/O buffer
  2511                              <1> 	;
  2512                              <1> 	; ((AX = R1)) input/output
  2513                              <1> 	; ((BX = R5)) output 
  2514                              <1> 	;
  2515                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2516                              <1> 	;
  2517 00005D2E E851010000          <1> 	call 	bufaloc
  2518                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2519                              <1> 			       ; / get a free I/O buffer
  2520                              <1> 	;;jc	error ; 20/07/2013
  2521 00005D33 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2522                              <1>        		; br 1f / branch if block already in a I/O buffer
  2523                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2524 00005D35 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2525                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2526                              <1> 		               ; / I/O queue entry for buffer
  2527 00005D3A E8B0000000          <1> 	call	poke
  2528                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2529                              <1> 			    ; /	bit 10=1 says read
  2530                              <1> 	; 09/06/2015
  2531                              <1> 	;jnc	short dskrd_1
  2532                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2533                              <1> 	;jmp	error
  2534                              <1> 	; 08/02/2022
  2535 00005D3F 7212                <1> 	jc	short dskrd_3
  2536                              <1> dskrd_1: ; 1:
  2537                              <1>        		;clr *$ps
  2538 00005D41 66F7030024          <1>        	test	word [ebx], 2400h
  2539                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2540                              <1> 				; / jump to idle
  2541 00005D46 7407                <1>        	jz	short dskrd_2
  2542                              <1> 		; beq 1f
  2543                              <1>         ;;mov   ecx, [s.wait_]
  2544 00005D48 E836F2FFFF          <1>        	call	idle
  2545                              <1> 		; jsr r0,idle; s.wait+2
  2546 00005D4D EBF2                <1> 	jmp 	short dskrd_1
  2547                              <1>        		; br 1b
  2548                              <1> dskrd_2: ; 1:
  2549 00005D4F 83C308              <1>         add	ebx, 8
  2550                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2551                              <1> 			  ; / just read in
  2552 00005D52 C3                  <1>        	retn
  2553                              <1> 		; rts r0
  2554                              <1> dskrd_err: 
  2555                              <1> 	; 08/02/2022
  2556                              <1> 	; (jump from 'bread' error)
  2557                              <1> dskrd_3:	
  2558                              <1> 	; 08/02/2022
  2559 00005D53 803D[BE6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2560 00005D5A 7509                <1> 	jne	short dskrd_4 ; no
  2561                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2562 00005D5C C605[BE6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2563 00005D63 EB0A                <1> 	jmp	short dskrd_5
  2564                              <1> dskrd_4:
  2565 00005D65 C705[AB6F0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2565 00005D6D 0000                <1>
  2566                              <1> dskrd_5:
  2567 00005D6F E967DDFFFF          <1> 	jmp	error
  2568                              <1> 
  2569                              <1> bwslot:
  2570                              <1> 	; 04/02/2022
  2571                              <1> 	; 10/07/2015
  2572                              <1> 	;	If the block/sector is not placed in a buffer
  2573                              <1> 	;	before 'wslot', it must be read before
  2574                              <1> 	;	it is written! (Otherwise transfer counts less
  2575                              <1> 	;	than 512 bytes will be able to destroy existing 
  2576                              <1> 	;	data on disk.)
  2577                              <1> 	;
  2578                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2579                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2580                              <1> 	; Retro UNIX 8086 v1 modification !
  2581                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2582                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2583                              <1> 	;	-> eAX = block number
  2584                              <1> 	;
  2585 00005D74 E818010000          <1> 	call	bufaloc_0
  2586 00005D79 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2587                              <1> 	; 04/02/2022
  2588                              <1> 	; ebx = buffer header address
  2589                              <1> bwslot_0:
  2590                              <1> 	; 10/07/2015
  2591 00005D7B 8B35[6C6F0000]      <1> 	mov	esi, [u.fofp]
  2592 00005D81 8B06                <1> 	mov	eax, [esi]
  2593 00005D83 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2594 00005D88 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2595                              <1> 		       ; recent disk data must be placed in the buffer
  2596 00005D8A 813D[806F0000]0002- <1> 	cmp	dword [u.count], 512
  2596 00005D92 0000                <1>
  2597 00005D94 730F                <1> 	jnb	short wslot_0	
  2598                              <1> bwslot_1:
  2599 00005D96 E89AFFFFFF          <1> 	call	dskrd_0
  2600                              <1> 	; 04/02/2022
  2601                              <1> 	; ebx = buffer data address = buffer header address + 8
  2602 00005D9B 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2603 00005D9E EB05                <1> 	jmp 	short wslot_0
  2604                              <1> 
  2605                              <1> wslot:
  2606                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2607                              <1> 	; 		(32 bit modifications)
  2608                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2609                              <1> 	;
  2610                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2611                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2612                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2613                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2614                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2615                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2616                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2617                              <1> 	;
  2618                              <1> 	; INPUTS ->
  2619                              <1>  	;    r1 - block number
  2620                              <1> 	;    cdev - current (block/disk) device number
  2621                              <1>  	;
  2622                              <1> 	; OUTPUTS ->
  2623                              <1> 	;    bufp - bits 9 and 15 are set, 
  2624                              <1> 	;           the remainder of the word left unchanged
  2625                              <1> 	;    r5 - points to first data word in I/O buffer
  2626                              <1> 	;
  2627                              <1> 	; ((AX = R1)) input/output
  2628                              <1> 	; ((BX = R5)) output 
  2629                              <1> 	;
  2630                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2631                              <1> 
  2632 00005DA0 E8DF000000          <1> 	call	bufaloc
  2633                              <1> 	; 10/07/2015
  2634                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2635                              <1>         	; br 1f / word in buffer in r5
  2636                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2637                              <1>         ; eAX = Block/Sector number (r1)
  2638                              <1> wslot_0: ;1:
  2639 00005DA5 66F7030024          <1>      	test	word [ebx], 2400h
  2640                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2641                              <1> 				; / of I/O queue entry
  2642 00005DAA 7407                <1> 	jz	short wslot_1
  2643                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2644                              <1> 		        ; / or not waiting to read)
  2645                              <1> 
  2646                              <1>         ;;mov	ecx, [s.wait_] ; 29/07/2013
  2647 00005DAC E8D2F1FFFF          <1> 	call	idle
  2648                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2649                              <1>        	                     ; / idle
  2650 00005DB1 EBF2                <1> 	jmp	short wslot_0
  2651                              <1> 		; br 1b / till finished
  2652                              <1> wslot_1: ;1:
  2653 00005DB3 66810B0082          <1> 	or      word [ebx], 8200h
  2654                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2655                              <1>                             	 ; / (write, inhibit bits)
  2656                              <1>        		; clr *$ps / clear processor status
  2657 00005DB8 83C308              <1> 	add	ebx, 8 ; 11/06/2015
  2658                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2659                              <1> 			  ; / for this block
  2660                              <1> dskwr_1:	; 08/02/2022
  2661 00005DBB C3                  <1> 	retn
  2662                              <1> 		; rts r0
  2663                              <1> dskwr:
  2664                              <1> 	; 12/02/2022
  2665                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2666                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2667                              <1> 	;
  2668                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2669                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2670                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2671                              <1> 	; previously has supplied all the information required in the
  2672                              <1> 	; I/O queue entry.
  2673                              <1> 	;
  2674                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2675                              <1> 	;
  2676                              <1> 	;
  2677 00005DBC 8B1D[1C6F0000]      <1> 	mov	ebx, [bufp]
  2678 00005DC2 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2679                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2680                              <1>                                   ; / bottom of queue
  2681 00005DC7 E823000000          <1> 	call	poke
  2682                              <1> 	; 09/06/2015
  2683 00005DCC 73ED                <1> 	jnc	short dskwr_1
  2684                              <1> 	; 12/02/2022
  2685 00005DCE 803D[BE6F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2686 00005DD5 7509                <1> 	jne	short dskwr_0 ; no
  2687                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2688 00005DD7 C605[BE6F0000]00    <1> 	mov	byte [u.brwdev], 0
  2689 00005DDE EB0A                <1> 	jmp	short dskwr_2
  2690                              <1> dskwr_0:
  2691 00005DE0 C705[AB6F0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2691 00005DE8 0000                <1>
  2692                              <1> dskwr_2:
  2693 00005DEA E9ECDCFFFF          <1> 	jmp	error
  2694                              <1> ;dskwr_1:
  2695                              <1> ;	retn
  2696                              <1> 
  2697                              <1> ;ppoke:
  2698                              <1>        		; mov $340,*$ps
  2699                              <1>        		; jsr r0,poke
  2700                              <1>        		; clr *$ps
  2701                              <1> 		; rts r0
  2702                              <1> poke:
  2703                              <1> 	; 04/02/2022 (32 bit reg push pop)
  2704                              <1> 	; 24/10/2015
  2705                              <1> 	; 20/08/2015
  2706                              <1> 	; 18/08/2015
  2707                              <1> 	; 02/07/2015
  2708                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2709                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2710                              <1> 	;
  2711                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2712                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2713                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2714                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2715                              <1> 	;
  2716                              <1> 	; Basic I/O functions for all block structured devices
  2717                              <1> 	;
  2718                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2719                              <1> 	;
  2720                              <1> 	; 20/07/2013 modifications
  2721                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2722                              <1> 	; INPUTS -> 
  2723                              <1> 	;        (EBX = buffer header address)
  2724                              <1> 	; OUTPUTS ->
  2725                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2726                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2727                              <1> 	;		(drive not ready or r/w error!)
  2728                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2729                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2730                              <1> 	;        (also it indicates invalid buffer data)
  2731                              <1> 	;
  2732 00005DEF 53                  <1> 	push	ebx
  2733                              <1>        		; mov r1,-(sp)
  2734                              <1>        		; mov r2,-(sp)
  2735                              <1>        		; mov r3,-(sp)
  2736 00005DF0 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2737                              <1> 	;
  2738                              <1> 	; 09/06/2015
  2739                              <1> 	; (permit read/write after a disk R/W error)
  2740 00005DF1 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2741 00005DF3 B001                <1> 	mov	al, 1
  2742 00005DF5 D2E0                <1> 	shl	al, cl
  2743 00005DF7 8405[446F0000]      <1> 	test 	al, [active] ; busy ? (error)
  2744 00005DFD 7408                <1> 	jz	short poke_0
  2745 00005DFF F6D0                <1> 	not	al
  2746 00005E01 2005[446F0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2747                              <1> poke_0:
  2748 00005E07 BE[3C6F0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2749                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2750                              <1> 					 ; / I/O queue pointer
  2751                              <1> poke_1: ; 1:
  2752 00005E0C 83EE04              <1>         sub	esi, 4
  2753 00005E0F 8B1E                <1> 	mov	ebx, [esi]
  2754                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2755 00005E11 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2756 00005E14 F6C406              <1>        	test	ah, 06h
  2757                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2758                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2759                              <1> 			       ; / queue entry
  2760 00005E17 745C                <1>         jz      short poke_5
  2761                              <1> 		; beq 2f / branch to 2f if both are clear
  2762                              <1> 	; 31/07/2013
  2763                              <1> 	;test	ah, 0B0h ; (*)
  2764                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2765                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2766                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2767                              <1> 		; bne 2f / branch if any are set
  2768                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2769                              <1>     		; movb (r1),r3 / get device id
  2770 00005E19 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2771                              <1> 	;mov	edi, ecx ; 26/04/2013
  2772 00005E1C 31C0                <1> 	xor 	eax, eax ; 0
  2773                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2774                              <1> 		; tstb deverr(r3) / test for errors on this device
  2775                              <1>        	;jna	short poke_2 
  2776                              <1> 		; beq 3f / branch if no errors
  2777                              <1> 	; 02/07/2015
  2778                              <1> 	;dec	eax
  2779                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2780                              <1>        		; mov $-1,2(r1) / destroy associativity
  2781                              <1> 	;shr	eax, 24
  2782                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2783                              <1> 		; clrb 1(r1) / do not do I/O
  2784                              <1> 	;jmp     short poke_5
  2785                              <1>         ;       ; br 2f
  2786                              <1>                 ; rts r0
  2787                              <1> poke_2: ; 3:
  2788                              <1> 	; 02/07/2015
  2789 00005E1E FEC1                <1> 	inc	cl ; 0FFh -> 0
  2790 00005E20 7453                <1> 	jz	short poke_5
  2791 00005E22 FEC0                <1> 	inc	al ; mov ax, 1
  2792 00005E24 FEC9                <1> 	dec	cl
  2793 00005E26 7402                <1> 	jz	short poke_3
  2794                              <1> 	; 26/04/2013 Modification
  2795                              <1> 	;inc	al ; mov ax, 1
  2796                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2797                              <1> 	;jz	short poke_3 ; cl = 0
  2798 00005E28 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2799                              <1> poke_3:
  2800                              <1> 	;test	[active], ax
  2801 00005E2A 8405[446F0000]      <1> 	test	[active], al
  2802                              <1> 		; bit $2,active / test disk busy bit
  2803 00005E30 7543                <1> 	jnz     short poke_5
  2804                              <1> 		; bne 2f / branch if bit is set
  2805                              <1> 	;or	[active], ax
  2806 00005E32 0805[446F0000]      <1> 	or	[active], al
  2807                              <1> 		; bis $2,active / set disk busy bit
  2808                              <1> 	;push	ax
  2809                              <1> 	; 04/02/2022
  2810 00005E38 50                  <1> 	push	eax
  2811 00005E39 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2812                              <1> 	;mov    [edi+drv.error], ah
  2813                              <1> 	; 04/02/2022
  2814 00005E3E 58                  <1> 	pop	eax
  2815                              <1> 	;pop	ax
  2816 00005E3F 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2817                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2818                              <1> 	;jna	short poke_4
  2819                              <1> 		; tstb deverr(r3) / test for errors on this device
  2820                              <1>        		; beq 3f / branch if no errors
  2821                              <1> 	; 02/07/2015 (32 bit modification)
  2822                              <1> 	; 20/07/2013
  2823 00005E41 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2824                              <1>        		; mov $-1,2(r1) / destroy associativity
  2825 00005E48 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2826                              <1> 		; clrb 1(r1) / do not do I/O
  2827 00005E4D EB26                <1> 	jmp     short poke_5
  2828                              <1> poke_4:	; 20/07/2013
  2829                              <1> 	; 17/07/2013
  2830 00005E4F F6D0                <1> 	not 	al 
  2831 00005E51 2005[446F0000]      <1> 	and	[active], al ; reset, not busy
  2832                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2833                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2834 00005E57 668B03              <1> 	mov	ax, [ebx]
  2835                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2836 00005E5A 66250006            <1>         and	ax, 600h
  2837                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2838 00005E5E 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2839                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2840 00005E63 C0E403              <1> 	shl	ah, 3
  2841                              <1>        		; rol r3
  2842                              <1>                 ; rol r3
  2843                              <1>                 ; rol r3	
  2844 00005E66 660903              <1> 	or	[ebx], ax
  2845                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2846                              <1> 			   ; bits 12 and 13
  2847 00005E69 E815F1FFFF          <1> 	call	idle ; 18/01/2014
  2848                              <1> 	;; sti
  2849                              <1> 	;hlt 	; wait for a hardware interrupt
  2850                              <1> 	;; cli
  2851                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2852                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2853                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2854                              <1> 	; method, this procedure will wait for a time according to
  2855                              <1> 	; multi tasking and time sharing concept.
  2856                              <1> 	;
  2857                              <1> 	; 24/10/2015
  2858                              <1> 	;not	ax 
  2859 00005E6E 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2860 00005E72 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2861                              <1> poke_5: ;2:
  2862 00005E75 81FE[1C6F0000]      <1>         cmp     esi, bufp
  2863                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2864                              <1>                             ; / has been scanned
  2865 00005E7B 778F                <1> 	ja      short poke_1
  2866                              <1>                ; bhi 1b
  2867                              <1> 	; 24/03/2013
  2868                              <1>        		; mov (sp)+,r3
  2869                              <1>        		; mov (sp)+,r2
  2870                              <1>        		; mov (sp)+,r1
  2871 00005E7D 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2872 00005E7E 5B                  <1> 	pop 	ebx
  2873                              <1> 	; 02/07/2015 (32 bit modification)
  2874                              <1> 	; 20/07/2013
  2875                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2876 00005E7F 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2877                              <1> 	;	
  2878                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2879                              <1> 	; or written succesfully; even if an error occurs while
  2880                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2881                              <1> 	;
  2882                              <1> 	; 09/06/2015
  2883 00005E82 F5                  <1> 	cmc
  2884 00005E83 C3                  <1> 	retn
  2885                              <1>                 ; rts r0
  2886                              <1> 
  2887                              <1> bufaloc:
  2888                              <1> 	; 04/02/2022
  2889                              <1> 	; 20/08/2015
  2890                              <1> 	; 19/08/2015
  2891                              <1> 	; 02/07/2015
  2892                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2893                              <1> 	;	     (32 bit modifications)	
  2894                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2895                              <1> 	;
  2896                              <1> 	; bufaloc - Block device I/O buffer allocation
  2897                              <1> 	; 
  2898                              <1> 	; INPUTS ->
  2899                              <1> 	;    r1 - block number
  2900                              <1> 	;    cdev - current (block/disk) device number
  2901                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2902                              <1> 	; OUTPUTS ->
  2903                              <1> 	;    r5 - pointer to buffer allocated
  2904                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2905                              <1> 	;
  2906                              <1> 	; ((AX = R1)) input/output
  2907                              <1> 	; ((BX = R5)) output
  2908                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2909                              <1> 	;    zf=1 -> block already in a I/O buffer
  2910                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2911                              <1> 	;    ((DL = Device ID))
  2912                              <1> 	;    (((DH = 0 or 1)))
  2913                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2914                              <1> 	;    ((CX and DH will not be used after return)))
  2915                              <1> 
  2916                              <1> 	;;push 	esi ; ***
  2917                              <1> 		; mov r2,-(sp) / save r2 on stack
  2918                              <1>        		; mov $340,*$ps / set processor priority to 7
  2919                              <1> 		; 20/07/2013
  2920                              <1> 	; 26/04/2013
  2921                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2922                              <1> 	;mov	edi, rdev  ; offset mdev = offset rdev + 1
  2923                              <1> 	;add	edi, ebx
  2924                              <1> 	; 09/01/2022
  2925 00005E84 0FB63D[406F0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2926 00005E8B 81C7[426F0000]      <1> 	add	edi, rdev
  2927                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2928                              <1> 			;; eDI points to device id.
  2929 00005E91 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2930                              <1> 	; 11/06/2015
  2931 00005E94 80BB[DA660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2932 00005E9B 720F                <1> 	jb	short bufaloc_9
  2933 00005E9D C705[AB6F0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2933 00005EA5 0000                <1>
  2934 00005EA7 E92FDCFFFF          <1> 	jmp	error
  2935                              <1> bufaloc_9:
  2936 00005EAC 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2937                              <1> bufaloc_10: ; 02/07/2015
  2938 00005EAE 31ED                <1> 	xor 	ebp, ebp ; 0
  2939 00005EB0 55                  <1> 	push	ebp ; 0
  2940 00005EB1 89E5                <1>         mov     ebp, esp	
  2941                              <1> 	;
  2942                              <1> bufaloc_1: ;1:
  2943                              <1> 		; clr -(sp) / vacant buffer
  2944 00005EB3 BE[1C6F0000]        <1>         mov 	esi, bufp
  2945                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2946                              <1> 			     ; / entrys in buffer area
  2947                              <1> bufaloc_2: ;2:
  2948 00005EB8 8B1E                <1> 	mov	ebx, [esi]
  2949                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2950                              <1> 			    ; queue entry into r5
  2951 00005EBA 66F70300F6          <1> 	test	word [ebx], 0F600h
  2952                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2953 00005EBF 7503                <1>         jnz	short bufaloc_3
  2954                              <1> 		; bne 3f / branch when 
  2955                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2956                              <1>                        ; / (i.e., buffer busy)
  2957 00005EC1 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2958                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2959                              <1> 			; / found points to word 2 of I/O queue entry)
  2960                              <1> bufaloc_3: ;3:
  2961                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2962                              <1> 	;
  2963 00005EC4 3813                <1> 	cmp	[ebx], dl	
  2964                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2965                              <1> 			       ; / as current device
  2966 00005EC6 7508                <1> 	jne	short bufaloc_4
  2967                              <1>        		; bne 3f
  2968 00005EC8 394304              <1> 	cmp	[ebx+4], eax
  2969                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2970                              <1> 			     ; / same as current block number
  2971 00005ECB 7503                <1>        	jne	short bufaloc_4
  2972                              <1> 		; bne 3f
  2973                              <1> 	;add	esp, 4
  2974 00005ECD 59                  <1> 	pop	ecx
  2975                              <1>        		; tst (sp)+ / bump stack pointer
  2976 00005ECE EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2977                              <1> 				; jump to bufaloc_6 in original Unix v1
  2978                              <1>        		; br 1f / use this buffer
  2979                              <1> bufaloc_4: ;3:
  2980 00005ED0 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2981                              <1> 	;
  2982 00005ED3 81FE[346F0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2983                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2984 00005ED9 72DD                <1> 	jb	short bufaloc_2
  2985                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2986                              <1>                        ; / buffers not checked)
  2987 00005EDB 5E                  <1>         pop	esi
  2988                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2989                              <1> 			     ; / to last free block
  2990 00005EDC 09F6                <1>        	or	esi, esi 
  2991 00005EDE 7507                <1> 	jnz	short bufaloc_5
  2992                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2993                              <1> 	        ; / if a free buffer is found branch to 2f
  2994                              <1>         ;; mov  ecx, [s.wait_]
  2995 00005EE0 E89EF0FFFF          <1> 	call	idle
  2996                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2997 00005EE5 EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2998                              <1>        		; br 1b
  2999                              <1> bufaloc_5: ;2:
  3000                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3001 00005EE7 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3002                              <1> bufaloc_6: ;1:
  3003 00005EE9 8B1E                <1>         mov    	ebx, [esi] 
  3004                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3005                              <1> 			     ; / entry in r5
  3006                              <1> 	;; 26/04/2013
  3007                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3008 00005EEB 8813                <1> 	mov 	[ebx], dl
  3009                              <1> 		; movb cdev,(r5) / put current device number 
  3010                              <1> 				 ; / in I/O queue entry
  3011 00005EED 894304              <1> 	mov 	[ebx+4], eax
  3012                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3013                              <1> 			     ; / of I/O queue entry
  3014                              <1> bufaloc_7: ;1:
  3015 00005EF0 81FE[1C6F0000]      <1>         cmp	esi, bufp
  3016                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3017                              <1> 			     ; / and put latest assigned
  3018 00005EF6 760A                <1> 	jna	short bufaloc_8	
  3019                              <1>        		; blos 1f / buffer on the top 
  3020                              <1> 			; / (this makes if the lowest priority)
  3021 00005EF8 83EE04              <1> 	sub	esi, 4
  3022 00005EFB 8B0E                <1> 	mov	ecx, [esi]
  3023 00005EFD 894E04              <1> 	mov	[esi+4], ecx
  3024                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3025 00005F00 EBEE                <1> 	jmp 	short bufaloc_7        
  3026                              <1> 		; br 1b
  3027                              <1> bufaloc_8: ;1:
  3028 00005F02 891E                <1>         mov	[esi], ebx
  3029                              <1> 		; mov r5,(r2)
  3030                              <1> 	;;pop	esi ; ***
  3031                              <1>        		; mov (sp)+,r2 / restore r2
  3032 00005F04 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3033                              <1> 		; Retro UNIX 8086 v1 modification
  3034                              <1> 		; zf=1 --> block already is in an I/O buffer
  3035                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3036 00005F06 C3                  <1> 	retn
  3037                              <1> 		; rts r0
  3038                              <1> 
  3039                              <1> diskio:
  3040                              <1> 	; 12/02/2022
  3041                              <1> 	; 04/02/2022 (Retro UNIX 386 v1 2022, Kernel v0.2.0.18)
  3042                              <1> 	; 10/07/2015
  3043                              <1> 	; 02/07/2015
  3044                              <1> 	; 16/06/2015
  3045                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3046                              <1> 	;	     (80386 protected mode modifications)	
  3047                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3048                              <1> 	;
  3049                              <1> 	; Retro UNIX 8086 v1 feature only !
  3050                              <1> 	;
  3051                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3052                              <1> 	; 04/07/2009 - 20/07/2011
  3053                              <1> 	;
  3054                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3055                              <1> 	;
  3056                              <1>         ; INPUTS ->
  3057                              <1> 	; 	   eBX = System I/O Buffer header address
  3058                              <1> 	;
  3059                              <1>         ; OUTPUTS -> cf=0 --> done 
  3060                              <1> 	; 	     cf=1 --> error code in AH
  3061                              <1> 	;
  3062                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3063                              <1> 	
  3064                              <1> ;rw_disk_sector:
  3065                              <1> 	; 12/02/2022
  3066                              <1> 	; 10/07/2015
  3067                              <1> 	; 02/07/2015
  3068                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3069                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3070                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3071                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3072                              <1> 	;
  3073                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3074 00005F07 B602                <1> 	mov	dh, 2
  3075 00005F09 668B03              <1> 	mov	ax, [ebx] 
  3076                              <1> 	;
  3077 00005F0C 56                  <1> 	push	esi ; ****
  3078 00005F0D 53                  <1> 	push	ebx ; ***
  3079                              <1> 	;
  3080 00005F0E 0FB6C8              <1> 	movzx	ecx, al
  3081 00005F11 89CE                <1> 	mov	esi, ecx
  3082                              <1> 	;
  3083 00005F13 38F1                <1> 	cmp	cl, dh ; 2
  3084 00005F15 7202                <1> 	jb	short rwdsk0
  3085 00005F17 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3086                              <1> rwdsk0:
  3087 00005F19 A2[8B660000]        <1> 	mov	[drv], al
  3088 00005F1E 81C6[DA660000]      <1> 	add	esi, drv.status
  3089                              <1> 	; 11/06/2015
  3090 00005F24 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3091 00005F27 7204                <1> 	jb      short rwdsk1
  3092                              <1> 	; 'drive not ready' error
  3093                              <1> 	; 12/02/2022
  3094                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3095                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3096                              <1> 	;;jmp	error
  3097                              <1> 	;stc	; cf = 1
  3098                              <1> 	;retn
  3099                              <1> 	; 12/02/2022
  3100 00005F29 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3101 00005F2B EB20                <1> 	jmp	short rwdsk_err1
  3102                              <1> rwdsk1:
  3103 00005F2D F6C402              <1> 	test	ah, 2
  3104                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3105                              <1> 			 ; write bit
  3106 00005F30 7402                <1> 	jz	short rwdsk2
  3107                              <1> 	;test	ah, 4
  3108                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3109                              <1> 	;		 ; read bit
  3110                              <1> 	;jz	short diskio_ret
  3111 00005F32 FEC6                <1> 	inc	dh ; 03h = write
  3112                              <1> rwdsk2:
  3113 00005F34 88C2                <1> 	mov	dl, al
  3114 00005F36 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3115 00005F39 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3116 00005F3B C0E102              <1> 	shl	cl, 2
  3117 00005F3E 81C1[BE660000]      <1> 	add	ecx, drv.size ; disk size
  3118 00005F44 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3119 00005F46 7214                <1> 	jb      short rwdsk3
  3120                              <1>  	; 'out of volume' error
  3121                              <1> 	; 12/02/2022
  3122                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3123                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3124                              <1> 	;;jmp	error
  3125                              <1> 	;stc	; cf = 1
  3126                              <1> 	;retn
  3127                              <1> 	; 12/02/2022
  3128 00005F48 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3129                              <1> rwdsk_err1:
  3130 00005F4D C605[BE6F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3131 00005F54 890D[AB6F0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3132 00005F5A EB30                <1> 	jmp	short rwdsk_err2
  3133                              <1> rwdsk3:
  3134                              <1> 	; 11/06/2015
  3135 00005F5C 83C304              <1> 	add	ebx, 4 ; buffer address
  3136 00005F5F C605[DA6F0000]04    <1> 	mov	byte [retry_count], 4
  3137 00005F66 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3138 00005F69 7432                <1>         jz      short rwdsk_chs
  3139                              <1> rwdsk_lba:
  3140                              <1> 	; LBA read/write (with private LBA function) 
  3141                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3142 00005F6B 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3143 00005F6E 89C1                <1> 	mov	ecx, eax ; sector number
  3144                              <1> 	; ebx = buffer (data) address
  3145                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3146                              <1> rwdsk_lba_retry:
  3147                              <1> 	;mov	dl, [drv]
  3148                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3149 00005F70 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3150 00005F72 00F4                <1> 	add	ah, dh		
  3151 00005F74 B001                <1> 	mov	al, 1
  3152                              <1> 	;int	13h
  3153 00005F76 E83EC6FFFF          <1> 	call	int13h
  3154 00005F7B 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3155 00005F7D 730E                <1> 	jnc	short rwdsk_lba_ok
  3156 00005F7F 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3157 00005F82 7408                <1>         je      short rwdsk_lba_fails
  3158 00005F84 FE0D[DA6F0000]      <1> 	dec	byte [retry_count]
  3159 00005F8A 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3160                              <1> rwdsk_err2:	; 12/02/2022
  3161                              <1> rwdsk_lba_fails:
  3162 00005F8C F9                  <1> 	stc
  3163                              <1> rwdsk_lba_ok:
  3164 00005F8D 5B                  <1> 	pop	ebx ; ***
  3165 00005F8E 5E                  <1> 	pop	esi ; ****
  3166 00005F8F C3                  <1> 	retn
  3167                              <1> rwdsk_lba_reset:
  3168 00005F90 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3169                              <1> 	;int	13h
  3170 00005F92 E822C6FFFF          <1>         call	int13h
  3171 00005F97 73D7                <1> 	jnc     short rwdsk_lba_retry
  3172 00005F99 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3173 00005F9B EBF0                <1> 	jmp	short rwdsk_lba_ok
  3174                              <1> 	;
  3175                              <1> 	; CHS read (convert LBA address to CHS values)	
  3176                              <1> rwdsk_chs:
  3177                              <1> 	; 10/07/2015
  3178 00005F9D 81EE[DA660000]      <1> 	sub	esi, drv.status
  3179 00005FA3 89F1                <1> 	mov	ecx, esi
  3180 00005FA5 81C6[E1660000]      <1> 	add 	esi, drv.error
  3181                              <1> 	; 02/07/2015
  3182                              <1> 	; 16/06/2015
  3183                              <1>  	; 11/06/2015 
  3184 00005FAB 53                  <1> 	push	ebx ; ** ; buffer
  3185 00005FAC D1E1                <1> 	shl	ecx, 1
  3186 00005FAE 51                  <1> 	push	ecx ; * 
  3187                              <1> 	;
  3188 00005FAF 89CB                <1> 	mov	ebx, ecx
  3189 00005FB1 8835[D96F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3190 00005FB7 31D2                <1> 	xor	edx, edx ; 0
  3191                              <1> 	; 04/02/2022
  3192                              <1> 	;sub	ecx, ecx 
  3193 00005FB9 81C3[B0660000]      <1>         add     ebx, drv.spt
  3194 00005FBF 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3195                              <1> 		; EDX:EAX = LBA
  3196 00005FC2 F7F1                <1> 	div	ecx
  3197 00005FC4 88D1                <1> 	mov	cl, dl	; sector number - 1
  3198 00005FC6 FEC1                <1> 	inc	cl	; sector number (1 based)
  3199 00005FC8 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3200                              <1> 	;push	cx
  3201                              <1>         ; 04/02/2022
  3202 00005FC9 51                  <1> 	push	ecx
  3203 00005FCA 81C3[A2660000]      <1>         add     ebx, drv.heads
  3204 00005FD0 668B0B              <1> 	mov	cx, [ebx] ; heads
  3205 00005FD3 31D2                <1> 	xor	edx, edx
  3206                              <1> 		; EAX = cylinders * heads + head
  3207 00005FD5 F7F1                <1> 	div	ecx
  3208                              <1> 	;pop	cx     ; sector number
  3209                              <1> 	; 04/02/2022
  3210 00005FD7 59                  <1> 	pop	ecx
  3211 00005FD8 88D6                <1> 	mov	dh, dl ; head number
  3212 00005FDA 8A15[8B660000]      <1> 	mov	dl, [drv]
  3213 00005FE0 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3214 00005FE2 C0E406              <1> 	shl	ah, 6
  3215 00005FE5 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3216                              <1> 		       ; sector (bits 0-7)
  3217 00005FE7 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3218                              <1> 		; CL = sector (bits 0-5)
  3219                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3220                              <1> 		; CH = cylinder (bits 0-7)
  3221                              <1> 		; DH = head
  3222                              <1> 		; DL = drive
  3223                              <1> 	;
  3224 00005FE8 C605[DA6F0000]04    <1> 	mov	byte [retry_count], 4
  3225                              <1> rwdsk_retry:	
  3226 00005FEF 8A25[D96F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3227 00005FF5 B001                <1> 	mov	al, 1 ; sector count	
  3228                              <1> 	;int	13h
  3229 00005FF7 E8BDC5FFFF          <1> 	call	int13h
  3230 00005FFC 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3231 00005FFE 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3232 00006000 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3233 00006003 7408                <1> 	je	short rwdsk_fails
  3234 00006005 FE0D[DA6F0000]      <1> 	dec	byte [retry_count]
  3235 0000600B 7504                <1> 	jnz	short rwdsk_reset
  3236                              <1> rwdsk_fails:
  3237 0000600D F9                  <1> 	stc
  3238                              <1> rwdsk_ok:
  3239 0000600E 5B                  <1> 	pop	ebx ; ***
  3240 0000600F 5E                  <1> 	pop	esi ; ****
  3241 00006010 C3                  <1> 	retn
  3242                              <1> rwdsk_reset:
  3243                              <1> 	; 02/02/2015
  3244 00006011 28E4                <1> 	sub	ah, ah
  3245 00006013 80FA80              <1> 	cmp	dl, 80h
  3246 00006016 7202                <1> 	jb	short rwdsk_fd_reset
  3247 00006018 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3248                              <1> rwdsk_fd_reset:
  3249                              <1> 	;int	13h
  3250 0000601A E89AC5FFFF          <1>         call	int13h
  3251 0000601F 73CE                <1> 	jnc	short rwdsk_retry
  3252 00006021 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3253 00006023 EBE9                <1> 	jmp 	short rwdsk_ok
  3254                              <1> 
  3255                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3256                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3257                              <1> ;
  3258                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3259                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3260                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3261                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3262                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3263                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3264                              <1> ; as in original unix v1.
  3265                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3266                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3267                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3268                              <1> ;
  3269                              <1> ; Erdogan tan (10/07/2015) 
  3270                              <1> 
  3271                              <1> ;drum: / interrupt handler
  3272                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3273                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3274                              <1> ;                                      / error
  3275                              <1> ;               br 3f / no, error
  3276                              <1> ;       br      2f / error
  3277                              <1> ;
  3278                              <1> ;disk:
  3279                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3280                              <1> ;       jmp     *$0f
  3281                              <1> ;0:
  3282                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3283                              <1> ;      	        br 3f / no, errors
  3284                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3285                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3286                              <1> ;                        / to 1f
  3287                              <1> ;       br      4f
  3288                              <1> ;1:
  3289                              <1> ;       bit     $20000,rkcs
  3290                              <1> ;       beq     4f / wait for seek complete
  3291                              <1> ;       mov     $0b,0b-2
  3292                              <1> ;       mov     rkap,r1
  3293                              <1> ;2:
  3294                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3295                              <1> ;                          / the disk buffer
  3296                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3297                              <1> ;       inc     r1
  3298                              <1> ;       asr     (r1)
  3299                              <1> ;       asr     (r1)
  3300                              <1> ;       asr     (r1) / reissue request
  3301                              <1> ;       dec     r1
  3302                              <1> ;3:
  3303                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3304                              <1> ;       mov     ac,-(sp)
  3305                              <1> ;       mov     mq,-(sp) / put these on the stack
  3306                              <1> ;       mov     sc,-(sp)
  3307                              <1> ;       jsr     r0,poke
  3308                              <1> ;       mov     (sp)+,sc
  3309                              <1> ;       mov     (sp)+,mq / pop them off stack
  3310                              <1> ;       mov     (sp)+,ac
  3311                              <1> ;4:
  3312                              <1> ;       jmp     retisp / u4-3
  3313                              <1> ;
  3314                              <1> ;trapt:                  / r2 points to the
  3315                              <1> ;       mov     (r0)+,r2 / device control register
  3316                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3317                              <1> ;       tst     (sp)+
  3318                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3319                              <1> ;       bge     4b / device still active so branch
  3320                              <1> ;       bit     (r0),active / was device busy?
  3321                              <1> ;       beq     4b / no, stray interrupt
  3322                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3323                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3324                              <1> ;       bge     2f / if no error jump to 2f
  3325                              <1> ;       tst     (r0)+ / skip on error
  3326                              <1> ; 2:
  3327                              <1> ;       jmp     (r0)
  2055                                  %include 'u9.s'        ; 29/06/2015
  2056                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.18) - SYS9.INC
  2057                              <1> ; Last Modification: 27/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 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2068                              <1> ;
  2069                              <1> ; ****************************************************************************
  2070                              <1> ; 21/11/2015
  2071                              <1> 
  2072                              <1> ; 04/02/2022 - Retro UNIX 386 v1 (Kernel v0.2.0.18)
  2073                              <1> ; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2074                              <1> 
  2075                              <1> getch:
  2076                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2077                              <1> 	; 30/06/2015
  2078                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2079 00006025 28C0                <1> 	sub	al, al ; 0
  2080                              <1> getch_q: ; 06/08/2015
  2081 00006027 8A25[C66B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2082 0000602D EB06                <1>         jmp     short getc_n
  2083                              <1> 
  2084                              <1> getc: 
  2085                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2086                              <1> 	; 12/11/2015
  2087                              <1> 	; 15/09/2015
  2088                              <1> 	; 01/07/2015
  2089                              <1> 	; 30/06/2015
  2090                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2091                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2092                              <1> 	;
  2093                              <1> 	; Retro UNIX 8086 v1 modification !
  2094                              <1> 	; 
  2095                              <1> 	; 'getc' gets (next) character 
  2096                              <1> 	;	 from requested TTY (keyboard) buffer 
  2097                              <1> 	; INPUTS ->
  2098                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2099                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2100                              <1> 	;	(Keyboard buffer will point to 
  2101                              <1> 	;			next character at next call)
  2102                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2103                              <1> 	;	(Keyboard buffer will point to 
  2104                              <1> 	;			current character at next call)
  2105                              <1> 	; OUTPUTS ->
  2106                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2107                              <1> 	;     			 ZF=0 -> AX has (current) character
  2108                              <1> 	;      AL = ascii code
  2109                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2110                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2111                              <1> 	; Original UNIX V1 'getc': 
  2112                              <1> 	;		get a character off character list
  2113                              <1> 	;
  2114                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2115                              <1> 	;
  2116                              <1> 	; 30/06/2015 (32 bit modifications)
  2117                              <1> 	; 16/07/2013
  2118                              <1> 	; mov 	[getctty], ah
  2119                              <1> 	;
  2120                              <1> 
  2121 0000602F 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2122                              <1> getc_n:
  2123                              <1> 	; 30/06/2015
  2124 00006035 08E4                <1> 	or	ah, ah
  2125 00006037 740D                <1> 	jz	short getc0 
  2126 00006039 D0E4                <1> 	shl	ah, 1
  2127 0000603B 0FB6DC              <1> 	movzx	ebx, ah
  2128 0000603E 81C3[C86B0000]      <1> 	add	ebx, ttychr
  2129 00006044 EB05                <1> 	jmp	short getc1
  2130                              <1> getc0:
  2131 00006046 BB[C86B0000]        <1> 	mov	ebx, ttychr
  2132                              <1> getc1:
  2133 0000604B 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2134                              <1> 				; (by kb_int)	
  2135 0000604E 6609C9              <1> 	or	cx, cx
  2136 00006051 7507                <1> 	jnz	short getc2
  2137 00006053 20C0                <1> 	and 	al, al
  2138 00006055 7415                <1> 	jz	short getc_s
  2139                              <1> 	;xor	ax, ax
  2140                              <1> 	; 24/12/2021
  2141 00006057 31C0                <1> 	xor	eax, eax
  2142 00006059 C3                  <1> 	retn
  2143                              <1> getc2:	
  2144 0000605A 20C0                <1> 	and	al, al
  2145 0000605C 6689C8              <1> 	mov	ax, cx
  2146 0000605F 66B90000            <1> 	mov	cx, 0
  2147 00006063 7506                <1> 	jnz	short getc3
  2148                              <1> getc_sn:
  2149 00006065 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2150 00006068 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2151                              <1> getc3:
  2152 0000606B C3                  <1> 	retn
  2153                              <1> getc_s:
  2154                              <1> 	; 12/11/2015
  2155                              <1> 	; 15/09/2015
  2156                              <1> 	; 01/07/2015
  2157                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2158                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2159                              <1> 	;
  2160                              <1> 	; tty  of the current process is not 
  2161                              <1> 	; current tty (ptty); so, current process only 
  2162                              <1> 	; can use keyboard input when its tty becomes 
  2163                              <1> 	; current tty (ptty).
  2164                              <1> 	; 'sleep' is for preventing an endless lock
  2165                              <1> 	; during this tty input request.
  2166                              <1> 	; (Because, the user is not looking at the video page
  2167                              <1> 	; of the process to undersand there is a keyboard
  2168                              <1> 	; input request.)
  2169                              <1> 	;
  2170                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2171                              <1> 	;
  2172                              <1> 	; 05/10/2013
  2173                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2174                              <1> 	;
  2175                              <1> 	; 10/10/2013
  2176                              <1> gcw0:
  2177 0000606C B10A                <1> 	mov	cl, 10 ; ch = 0
  2178                              <1> gcw1:	
  2179                              <1> 	; 12/11/2015
  2180 0000606E E86CDBFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2181                              <1> 	; 10/10/2013
  2182 00006073 E80BEFFFFF          <1> 	call	idle
  2183 00006078 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2184                              <1> 				; (by kb_int)
  2185 0000607B 6609C0              <1> 	or	ax, ax
  2186                              <1> ;	jnz	short gcw3
  2187 0000607E 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2188                              <1> 	; 30/06/2015
  2189 00006080 FEC9                <1> 	dec	cl
  2190 00006082 75EA                <1> 	jnz	short gcw1
  2191                              <1> 	;
  2192 00006084 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2193                              <1> ;	; 10/12/2013
  2194                              <1> ;	cmp 	ah, [ptty]
  2195                              <1> ;	jne	short gcw2
  2196                              <1> ;	; 14/02/2014
  2197                              <1> ;	cmp	byte [u.uno], 1
  2198                              <1> ;	jna	short gcw0		
  2199                              <1> ;gcw2:
  2200 0000608A E881EFFFFF          <1> 	call	sleep
  2201                              <1> 	;
  2202                              <1> 	; 20/09/2013
  2203 0000608F 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn]
  2204 00006095 30C0                <1> 	xor 	al, al
  2205 00006097 EB9C                <1> 	jmp	short getc_n
  2206                              <1> ;gcw3:
  2207                              <1> gcw2: 	; 15/09/2015
  2208                              <1> 	; 10/10/2013
  2209 00006099 30C9                <1> 	xor	cl, cl
  2210 0000609B EBC8                <1> 	jmp	short getc_sn
  2211                              <1> 
  2212                              <1> putc:	
  2213                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2214                              <1> 	; 13/08/2015
  2215                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2216                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2217                              <1> 	;
  2218                              <1> 	; Retro UNIX 8086 v1 modification !
  2219                              <1> 	; 
  2220                              <1> 	; 'putc' puts a character 
  2221                              <1> 	;	 onto requested (tty) video page or
  2222                              <1> 	;	 serial port
  2223                              <1> 	; INPUTS ->
  2224                              <1> 	;     AL = ascii code of the character
  2225                              <1> 	;     AH = video page (tty) number (0 to 7)
  2226                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2227                              <1> 	; OUTPUTS ->
  2228                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2229                              <1> 	;      			ZF=0 -> AX has (current) character
  2230                              <1> 	;     cf=0 and AH = 0 -> no error
  2231                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2232                              <1> 	; 
  2233                              <1> 	; Original UNIX V1 'putc': 
  2234                              <1> 	;     put a character at the end of character list
  2235                              <1> 	;
  2236                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2237                              <1> 	;
  2238 0000609D 80FC07              <1> 	cmp	ah, 7
  2239                              <1>         ;ja	sndc
  2240 000060A0 770A                <1>         ja      short sndc ; 24/12/2024
  2241                              <1> 	; 30/06/2015
  2242 000060A2 0FB6DC              <1> 	movzx	ebx, ah
  2243                              <1> 	; 13/08/2015
  2244 000060A5 B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2245 000060A7 E932B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2246                              <1> 
  2247                              <1> sndc:   ; <Send character>
  2248                              <1> 	;
  2249                              <1> 	; 12/01/2022
  2250                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2251                              <1> 	; 17/11/2015
  2252                              <1> 	; 16/11/2015
  2253                              <1> 	; 11/11/2015
  2254                              <1> 	; 10/11/2015
  2255                              <1> 	; 09/11/2015
  2256                              <1> 	; 08/11/2015
  2257                              <1> 	; 07/11/2015
  2258                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2259                              <1> 	; 29/10/2015
  2260                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2261                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2262                              <1> 	;
  2263                              <1> 	; Retro UNIX 8086 v1 feature only !
  2264                              <1> 	;
  2265                              <1> 	; ah = [u.ttyn]
  2266                              <1> 	;
  2267                              <1> 	; 30/06/2015
  2268 000060AC 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2269                              <1> 	; 07/11/2015
  2270 000060AF 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2271                              <1> sndc0:
  2272                              <1> 	; 07/11/2015
  2273 000060B2 E8A7EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2274 000060B7 7405                <1> 	jz	short sndc1
  2275 000060B9 E821DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2276                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2277                              <1> sndc1:
  2278                              <1> 	; 16/11/2015
  2279                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2280                              <1> 	; 24/12/2021
  2281 000060BE 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2282                              <1> sndcx:
  2283 000060C0 8A83[0A6C0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2284 000060C6 8AA3[086C0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2285                              <1> 	;
  2286                              <1> 	; 17/11/2015
  2287                              <1> 	; check 'request for response' status
  2288 000060CC 80BB[046C0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2289 000060D3 740A                <1> 	jz	short query
  2290                              <1> response:
  2291 000060D5 FE05[076C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2292 000060DB B0FF                <1> 	mov	al, 0FFh	 
  2293 000060DD EB14                <1> 	jmp	short sndc3
  2294                              <1> query:
  2295 000060DF 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2296 000060E1 750E                <1> 	jnz 	short sndc2 ; normal character
  2297                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2298                              <1> 	;je	short sndc2  ; yes, already responded
  2299                              <1> 	; 16/11/2015
  2300                              <1> 	; query: request for response (again)
  2301 000060E3 8883[086C0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2302 000060E9 FE05[076C0000]      <1> 	inc 	byte [comqr] ; query or response status
  2303 000060EF EB02                <1> 	jmp	short sndc3
  2304                              <1> sndc2:
  2305 000060F1 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2306                              <1> sndc3:
  2307 000060F3 8883[0A6C0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2308 000060F9 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2309                              <1> 	; 30/06/2015
  2310 000060FB E88ED4FFFF          <1> 	call	sp_status ; get serial port status
  2311                              <1> 	; AL = Line status, AH = Modem status
  2312                              <1> 	; 07/11/2015
  2313 00006100 A880                <1> 	test	al, 80h
  2314 00006102 7504                <1> 	jnz	short sndc4
  2315 00006104 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2316 00006106 751A                <1> 	jnz	short sndc5
  2317                              <1> sndc4: 	; Check line status again
  2318                              <1> 	; 16/11/2015
  2319                              <1> 	;push	cx
  2320                              <1> 	; 24/12/2021
  2321 00006108 51                  <1> 	push	ecx
  2322                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2323                              <1> 	; 12/01/2022
  2324 00006109 31C9                <1> 	xor	ecx, ecx
  2325 0000610B B106                <1> 	mov	cl, 6
  2326 0000610D E8C3B3FFFF          <1> 	call	WAITF
  2327                              <1> 	;pop	cx
  2328                              <1> 	; 24/12/1021
  2329 00006112 59                  <1> 	pop	ecx
  2330                              <1> 	;
  2331 00006113 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2332 00006115 E874D4FFFF          <1> 	call	sp_status ; get serial port status
  2333                              <1> 	; 16/11/2015
  2334                              <1> 	; 09/11/2015
  2335                              <1> 	; 08/11/2015
  2336 0000611A A880                <1> 	test	al, 80h	; time out error
  2337 0000611C 7565                <1>         jnz     short sndc7
  2338 0000611E A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2339 00006120 7461                <1>         jz	short sndc7
  2340                              <1> sndc5:  
  2341 00006122 8A83[0A6C0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2342 00006128 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2343 0000612C 28DE                <1> 	sub	dh, bl
  2344 0000612E EE                  <1> 	out	dx, al	   ; send on serial port
  2345                              <1> 	; 10/11/2015
  2346                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2347                              <1> 	; (to improve text flow to the terminal)
  2348                              <1> 	; ('diskette.inc': 'WAITF')
  2349                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2350                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2351                              <1> 	;push	cx
  2352                              <1> 	; 24/12/2021
  2353 0000612F 51                  <1> 	push	ecx
  2354                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2355                              <1> 	; 12/01/2022
  2356 00006130 29C9                <1> 	sub	ecx, ecx
  2357 00006132 B106                <1> 	mov	cl, 6
  2358 00006134 E89CB3FFFF          <1> 	call	WAITF
  2359                              <1> 	;pop	cx
  2360                              <1> 	; 24/12/1021
  2361 00006139 59                  <1> 	pop	ecx
  2362                              <1>     	;
  2363                              <1> 	; 07/11/2015
  2364 0000613A 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2365                              <1> 	;
  2366 0000613C E84DD4FFFF          <1> 	call	sp_status ; get serial port status
  2367                              <1> 	; AL = Line status, AH = Modem status
  2368                              <1> 	;
  2369 00006141 E818EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2370 00006146 7405                <1> 	jz	short sndc6
  2371 00006148 E892DAFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2372                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2373                              <1> sndc6:
  2374 0000614D 3C80                <1> 	cmp	al, 80h
  2375 0000614F 7332                <1> 	jnb	short sndc7		
  2376                              <1> 	;
  2377 00006151 803D[076C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2378 00006158 7244                <1> 	jb	short sndc8 	; no, normal character
  2379 0000615A 883D[076C0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2380                              <1> 	; 17/11/2015
  2381 00006160 E81EEEFFFF          <1> 	call	idle
  2382                              <1> 	;
  2383 00006165 38BB[0A6C0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2384                              <1>         ;ja	sndc2       ; response (will be followed by
  2385                              <1> 			    ; a normal character)
  2386                              <1> 	; 24/12/2021
  2387 0000616B 7602                <1> 	jna	short sndc_10
  2388 0000616D EB82                <1> 	jmp	sndc2
  2389                              <1> sndc_10:
  2390                              <1> 	; Query request must be responded by the terminal
  2391                              <1> 	; before sending a normal character !
  2392 0000616F 53                  <1> 	push	ebx
  2393                              <1> 	;push	cx ; *** cl = character (to be sent)
  2394                              <1> 	; 24/12/2021
  2395 00006170 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2396 00006171 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn]
  2397 00006177 E894EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2398                              <1> 		      ; received data available interrupt
  2399                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2400                              <1> 	; 24/12/2021
  2401 0000617C 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2402 0000617D 5B                  <1> 	pop	ebx
  2403 0000617E E93DFFFFFF          <1>         jmp	sndcx
  2404                              <1> sndc7:
  2405                              <1> 	 ; 16/11/2015
  2406 00006183 803D[076C0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2407 0000618A 7213                <1> 	jb	short sndc9 	; no
  2408                              <1> 	;
  2409 0000618C 88BB[086C0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2410 00006192 88BB[0A6C0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2411                              <1> 	;
  2412 00006198 883D[076C0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2413                              <1> sndc8:
  2414 0000619E F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2415                              <1> sndc9:
  2416                              <1> 	; AL = Line status, AH = Modem status
  2417 0000619F C3                  <1> 	retn
  2418                              <1> 
  2419                              <1> get_cpos:
  2420                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2421                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2422                              <1> 	;
  2423                              <1> 	; INPUT -> bl = video page number
  2424                              <1> 	; RETURN -> dx = cursor position
  2425                              <1> 
  2426 000061A0 53                  <1> 	push	ebx
  2427 000061A1 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2428 000061A4 D0E3                <1> 	shl	bl, 1
  2429 000061A6 81C3[B66B0000]      <1> 	add	ebx, cursor_posn
  2430 000061AC 668B13              <1> 	mov	dx, [ebx]
  2431 000061AF 5B                  <1> 	pop	ebx
  2432 000061B0 C3                  <1> 	retn
  2433                              <1> 
  2434                              <1> read_ac_current:
  2435                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2436                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2437                              <1> 	;
  2438                              <1> 	; INPUT -> bl = video page number
  2439                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2440                              <1> 
  2441 000061B1 E892B3FFFF          <1> 	call 	find_position ; 'video.inc'
  2442                              <1> 	; dx = status port
  2443                              <1> 	; esi = cursor location/address
  2444 000061B6 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2445 000061BC 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2446 000061BF C3                  <1> 	retn
  2447                              <1> 
  2448                              <1> syssleep:
  2449                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2450                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2451                              <1> 	;
  2452                              <1> 	; Retro UNIX 8086 v1 feature only
  2453                              <1> 	; (INPUT -> none)
  2454                              <1> 	;
  2455 000061C0 0FB61D[A56F0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2456 000061C7 8AA3[B76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2457 000061CD E83EEEFFFF          <1> 	call	sleep
  2458 000061D2 E924D9FFFF          <1> 	jmp	sysret
  2459                              <1> 
  2460                              <1> 	; 27/02/2022
  2461                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2462                              <1> %if 0
  2463                              <1> 
  2464                              <1> vp_clr:
  2465                              <1> 	; Reset/Clear Video Page
  2466                              <1> 	;
  2467                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2468                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2469                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2470                              <1> 	;
  2471                              <1> 	; Retro UNIX 8086 v1 feature only !
  2472                              <1> 	;
  2473                              <1> 	; INPUTS -> 
  2474                              <1> 	;   BL = video page number	 
  2475                              <1> 	;
  2476                              <1> 	; OUTPUT ->
  2477                              <1> 	;   none
  2478                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2479                              <1> 	;
  2480                              <1> 	; 04/12/2013
  2481                              <1> 	sub	al, al
  2482                              <1> 	; al = 0 (clear video page)
  2483                              <1> 	; bl = video page
  2484                              <1> 	mov	ah, 07h
  2485                              <1> 	; ah = 7 (attribute/color)
  2486                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2487                              <1> 	; 24/12/2021
  2488                              <1> 	xor	ecx, ecx
  2489                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2490                              <1> 	call	scroll_up
  2491                              <1> 	; bl = video page
  2492                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2493                              <1> 	; 24/12/2021
  2494                              <1> 	xor	edx, edx 
  2495                              <1> 	jmp 	set_cpos
  2496                              <1> 
  2497                              <1> %endif
  2498                              <1> 
  2499                              <1> sysmsg:
  2500                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2501                              <1> 	; 11/11/2015
  2502                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2503                              <1> 	; Print user-application message on user's console tty
  2504                              <1> 	;
  2505                              <1> 	; Input -> EBX = Message address
  2506                              <1> 	;	   ECX = Message length (max. 255)
  2507                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2508                              <1> 	;
  2509 000061D7 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2510                              <1> 	;ja	sysret ; nothing to do with big message size
  2511 000061DD 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2512 000061DF 08C9                <1> 	or	cl, cl
  2513                              <1> 	;jz	sysret
  2514 000061E1 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2515 000061E3 20D2                <1> 	and	dl, dl
  2516 000061E5 7502                <1> 	jnz	short sysmsg0
  2517 000061E7 B207                <1> 	mov	dl, 07h ; default color
  2518                              <1> 		; (black background, light gray character)
  2519                              <1> sysmsg0:
  2520 000061E9 891D[7C6F0000]      <1> 	mov	[u.base], ebx
  2521 000061EF 8815[C76B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2522 000061F5 89E5                <1> 	mov	ebp, esp
  2523 000061F7 31DB                <1> 	xor	ebx, ebx ; 0
  2524 000061F9 891D[846F0000]      <1> 	mov	[u.nread], ebx ; 0
  2525                              <1> 	;
  2526 000061FF 381D[BD6F0000]      <1> 	cmp	[u.kcall], bl ; 0
  2527 00006205 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2528                              <1> 	;
  2529 00006207 890D[806F0000]      <1> 	mov	[u.count], ecx
  2530 0000620D 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2531                              <1> 	; 24/12/2021
  2532                              <1> 	; (dword alignment for esp)
  2533 0000620E F6C103              <1> 	test	cl, 3
  2534 00006211 7404                <1> 	jz	short sysmsg_7
  2535 00006213 80C903              <1> 	or	cl, 3
  2536 00006216 41                  <1> 	inc	ecx
  2537                              <1> sysmsg_7:
  2538 00006217 29CC                <1> 	sub	esp, ecx
  2539 00006219 89E7                <1> 	mov	edi, esp
  2540 0000621B 89E6                <1> 	mov	esi, esp
  2541 0000621D 66891D[BB6F0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2542                              <1> 	; 11/11/2015
  2543 00006224 8A25[8C6F0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2544                              <1> 	; 0 = none
  2545 0000622A FECC                <1> 	dec	ah
  2546 0000622C 790C                <1> 	jns	short sysmsg1 
  2547 0000622E 8A1D[A56F0000]      <1> 	mov	bl, [u.uno] ; process number	
  2548 00006234 8AA3[B76C0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2549                              <1> sysmsg1:
  2550 0000623A 8825[AA6F0000]      <1> 	mov	[u.ttyn], ah
  2551                              <1> sysmsg2:
  2552 00006240 E823F5FFFF          <1> 	call	cpass
  2553 00006245 7416                <1> 	jz	short sysmsg5
  2554 00006247 AA                  <1> 	stosb
  2555 00006248 20C0                <1> 	and	al, al
  2556 0000624A 75F4                <1> 	jnz	short sysmsg2
  2557                              <1> sysmsg3:
  2558 0000624C 80FC07              <1> 	cmp	ah, 7 ; tty number
  2559 0000624F 7711                <1> 	ja	short sysmsg6 ; serial port
  2560 00006251 E83E000000          <1> 	call	print_cmsg
  2561                              <1> sysmsg4:
  2562 00006256 89EC                <1> 	mov	esp, ebp	
  2563                              <1> sysmsg8: ; 24/12/2021	
  2564 00006258 E99ED8FFFF          <1> 	jmp	sysret
  2565                              <1> sysmsg5:
  2566 0000625D C60700              <1> 	mov	byte [edi], 0
  2567 00006260 EBEA                <1> 	jmp	short sysmsg3
  2568                              <1> sysmsg6:
  2569 00006262 8A06                <1> 	mov	al, [esi]
  2570 00006264 E843FEFFFF          <1> 	call	sndc
  2571 00006269 72EB                <1> 	jc	short sysmsg4
  2572 0000626B 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2573 0000626E 76E6                <1> 	jna	short sysmsg4
  2574 00006270 46                  <1> 	inc 	esi
  2575 00006271 8A25[AA6F0000]      <1> 	mov	ah, [u.ttyn]
  2576 00006277 EBE9                <1> 	jmp	short sysmsg6
  2577                              <1> 
  2578                              <1> sysmsgk: ; Temporary (01/07/2015)
  2579                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2580                              <1> 	; (ECX -character count- will not be considered)
  2581 00006279 8B35[7C6F0000]      <1> 	mov	esi, [u.base]
  2582 0000627F 8A25[C66B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2583 00006285 8825[AA6F0000]      <1> 	mov	[u.ttyn], ah
  2584 0000628B C605[BD6F0000]00    <1> 	mov	byte [u.kcall], 0
  2585 00006292 EBB8                <1> 	jmp	short sysmsg3
  2586                              <1> 	
  2587                              <1> print_cmsg: 
  2588                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2589                              <1> 	;
  2590                              <1> 	; print message (on user's console tty) 
  2591                              <1> 	;	with requested color
  2592                              <1> 	;
  2593                              <1> 	; INPUTS:
  2594                              <1> 	;	esi = message address
  2595                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2596                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2597                              <1> 	;
  2598 00006294 AC                  <1> 	lodsb
  2599                              <1> pcmsg1:
  2600 00006295 56                  <1> 	push 	esi
  2601 00006296 0FB61D[AA6F0000]    <1>         movzx   ebx, byte [u.ttyn]
  2602 0000629D 8A25[C76B0000]      <1> 	mov	ah, [ccolor]
  2603 000062A3 E836B1FFFF          <1> 	call 	write_tty
  2604 000062A8 5E                  <1> 	pop	esi
  2605 000062A9 AC                  <1> 	lodsb
  2606 000062AA 20C0                <1> 	and 	al, al  ; 0
  2607 000062AC 75E7                <1> 	jnz 	short pcmsg1
  2608 000062AE C3                  <1> 	retn
  2609                              <1> 
  2610                              <1> sysgeterr:
  2611                              <1> 	; 16/02/2022
  2612                              <1> 	; 09/12/2015
  2613                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2614                              <1> 	; Get last error number or page fault count
  2615                              <1> 	; (for debugging)
  2616                              <1> 	;
  2617                              <1> 	; Input -> EBX = return type
  2618                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2619                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2620                              <1> 	;	   FFFFFFFEh = total page fault count
  2621                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2622                              <1> 	;
  2623                              <1> 	; Output -> EAX = last error number or page fault count
  2624                              <1> 	;	   (depending on EBX input)
  2625                              <1> 	; 	
  2626 000062AF 21DB                <1> 	and 	ebx, ebx
  2627 000062B1 750F                <1> 	jnz	short glerr_2
  2628                              <1> glerr_0:
  2629 000062B3 A1[AB6F0000]        <1> 	mov	eax, [u.error]
  2630                              <1> glerr_1:
  2631 000062B8 A3[5C6F0000]        <1> 	mov	[u.r0], eax
  2632                              <1>  	;retn
  2633                              <1> 	; 16/02/2022 (BugFix)
  2634 000062BD E939D8FFFF          <1> 	jmp	sysret
  2635                              <1> glerr_2:
  2636 000062C2 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2637 000062C3 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2638 000062C5 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2639 000062C6 75EB                <1> 	jnz	short glerr_0
  2640 000062C8 A1[506C0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2641 000062CD EBE9                <1>         jmp     short glerr_1
  2642                              <1> glerr_3:
  2643 000062CF A1[BF6F0000]        <1> 	mov 	eax, [u.pfcount]
  2644 000062D4 EBE2                <1> 	jmp	short glerr_1
  2056                                  
  2057                                  ; 07/03/2015
  2058                                  ; Temporary Code
  2059                                  display_disks:
  2060 000062D6 803D[8E660000]00        	cmp 	byte [fd0_type], 0
  2061 000062DD 7605                    	jna 	short ddsks1
  2062 000062DF E87D000000              	call	pdskm
  2063                                  ddsks1:
  2064 000062E4 803D[8F660000]00        	cmp	byte [fd1_type], 0
  2065 000062EB 760C                    	jna	short ddsks2
  2066 000062ED C605[7D680000]31        	mov	byte [dskx], '1'
  2067 000062F4 E868000000              	call	pdskm
  2068                                  ddsks2:
  2069 000062F9 803D[90660000]00        	cmp	byte [hd0_type], 0
  2070 00006300 7654                    	jna	short ddsk6
  2071 00006302 66C705[7B680000]68-     	mov	word [dsktype], 'hd'
  2071 0000630A 64                 
  2072 0000630B C605[7D680000]30        	mov	byte [dskx], '0'
  2073 00006312 E84A000000              	call	pdskm
  2074                                  ddsks3:
  2075 00006317 803D[91660000]00        	cmp	byte [hd1_type], 0
  2076 0000631E 7636                    	jna	short ddsk6
  2077 00006320 C605[7D680000]31        	mov	byte [dskx], '1'
  2078 00006327 E835000000              	call	pdskm
  2079                                  ddsks4:
  2080 0000632C 803D[92660000]00        	cmp	byte [hd2_type], 0
  2081 00006333 7621                    	jna	short ddsk6
  2082 00006335 C605[7D680000]32        	mov	byte [dskx], '2'
  2083 0000633C E820000000              	call	pdskm
  2084                                  ddsks5:
  2085 00006341 803D[93660000]00        	cmp	byte [hd3_type], 0
  2086 00006348 760C                    	jna	short ddsk6
  2087 0000634A C605[7D680000]33        	mov	byte [dskx], '3'
  2088 00006351 E80B000000              	call	pdskm
  2089                                  ddsk6:
  2090 00006356 BE[8C680000]            	mov	esi, nextline
  2091 0000635B E806000000              	call	pdskml
  2092                                  pdskm_ok:
  2093 00006360 C3                      	retn
  2094                                  pdskm:
  2095 00006361 BE[79680000]            	mov	esi, dsk_ready_msg
  2096                                  pdskml:	
  2097 00006366 AC                      	lodsb
  2098 00006367 08C0                    	or	al, al
  2099 00006369 74F5                    	jz	short pdskm_ok
  2100 0000636B 56                      	push	esi
  2101 0000636C 31DB                    	xor	ebx, ebx ; 0
  2102                                  			; Video page 0 (bl=0)
  2103 0000636E B407                    	mov	ah, 07h ; Black background, 
  2104                                  			; light gray forecolor
  2105 00006370 E869B0FFFF              	call	write_tty
  2106 00006375 5E                      	pop	esi
  2107 00006376 EBEE                    	jmp	short pdskml
  2108                                  
  2109 00006378 90<rep 8h>              align 16
  2110                                  
  2111                                  gdt:	; Global Descriptor Table
  2112                                  	; (30/07/2015, conforming cs)
  2113                                  	; (26/03/2015)
  2114                                  	; (24/03/2015, tss)
  2115                                  	; (19/03/2015)
  2116                                  	; (29/12/2013)
  2117                                  	;
  2118 00006380 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2119                                  	; 18/08/2014
  2120                                  			; 8h kernel code segment, base = 00000000h		
  2121 00006388 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2122                                  			; 10h kernel data segment, base = 00000000h	
  2123 00006390 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2124                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2125 00006398 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2126                                  			; 23h user data segment, base address = 400000h ; CORE
  2127 000063A0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2128                                  			; Task State Segment
  2129 000063A8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2130                                  			       ;  no IO permission in ring 3)
  2131                                  gdt_tss0:
  2132 000063AA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2133                                  gdt_tss1:
  2134 000063AC 00                      	db 0  ; TSS base address, bits 16-23 
  2135                                  	      		; 49h	
  2136 000063AD E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2137 000063AE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2138                                  gdt_tss2:
  2139 000063AF 00                      	db 0  ; TSS base address, bits 24-31 
  2140                                  
  2141                                  gdt_end:
  2142                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2143                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2144                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2145                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2146                                  
  2147                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2148                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2149                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2150                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2151                                  		; W= Writeable, A= Accessed
  2152                                  	
  2153                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2154                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2155                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2156                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2157                                  
  2158                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2159                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2160                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2161                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2162                                  	
  2163                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2164                                  
  2165                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2166                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2167                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2168                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2169                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2170                                  		; AVL= Available to programmers	
  2171                                  
  2172                                  gdtd:
  2173 000063B0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2174 000063B2 [80630000]                      dd gdt			; Address of the GDT
  2175                                  
  2176                                  	; 20/08/2014
  2177                                  idtd:
  2178 000063B6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2179 000063B8 [30690000]                      dd idt			; Address of the IDT
  2180                                  
  2181                                  Align 4
  2182                                  
  2183                                  	; 21/08/2014
  2184                                  ilist:
  2185                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2186                                  	;
  2187                                  	; Exception list
  2188                                  	; 25/08/2014	
  2189 000063BC [3B080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2190 000063C0 [42080000]              	dd	exc1	
  2191 000063C4 [49080000]              	dd 	exc2	
  2192 000063C8 [50080000]              	dd	exc3	
  2193 000063CC [54080000]              	dd	exc4	
  2194 000063D0 [58080000]              	dd	exc5	
  2195 000063D4 [5C080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2196 000063D8 [60080000]              	dd	exc7	
  2197 000063DC [64080000]              	dd	exc8	
  2198 000063E0 [68080000]              	dd	exc9	
  2199 000063E4 [6C080000]              	dd 	exc10	
  2200 000063E8 [70080000]              	dd	exc11
  2201 000063EC [74080000]              	dd	exc12
  2202 000063F0 [78080000]              	dd	exc13	; 0Dh, General Protection Fault
  2203 000063F4 [7C080000]              	dd 	exc14	; 0Eh, Page Fault
  2204 000063F8 [80080000]              	dd	exc15
  2205 000063FC [84080000]              	dd	exc16
  2206 00006400 [88080000]              	dd	exc17
  2207 00006404 [8C080000]              	dd 	exc18
  2208 00006408 [90080000]              	dd	exc19
  2209 0000640C [94080000]              	dd 	exc20
  2210 00006410 [98080000]              	dd	exc21
  2211 00006414 [9C080000]              	dd	exc22
  2212 00006418 [A0080000]              	dd	exc23
  2213 0000641C [A4080000]              	dd 	exc24
  2214 00006420 [A8080000]              	dd	exc25
  2215 00006424 [AC080000]              	dd	exc26
  2216 00006428 [B0080000]              	dd	exc27
  2217 0000642C [B4080000]              	dd 	exc28
  2218 00006430 [B8080000]              	dd	exc29
  2219 00006434 [BC080000]              	dd 	exc30
  2220 00006438 [C0080000]              	dd	exc31
  2221                                  	; Interrupt list
  2222 0000643C [77060000]              	dd	timer_int	; INT 20h
  2223                                  		;dd	irq0	
  2224 00006440 [7C0B0000]              	dd	keyb_int	; 27/08/2014
  2225                                  		;dd	irq1
  2226 00006444 [95070000]              	dd	irq2
  2227                                  		; COM2 int
  2228 00006448 [99070000]              	dd	irq3
  2229                                  		; COM1 int
  2230 0000644C [A4070000]              	dd	irq4
  2231 00006450 [AF070000]              	dd	irq5
  2232                                  ;DISKETTE_INT: ;06/02/2015
  2233 00006454 [66250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2234                                  		;dd	irq6
  2235                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2236                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2237 00006458 [2B0B0000]              	dd	default_irq7	; 25/02/2015
  2238                                  		;dd	irq7
  2239                                  ; Real Time Clock Interrupt
  2240 0000645C [C9090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2241                                  		;dd	irq8	; INT 28h
  2242 00006460 [BF070000]              	dd	irq9
  2243 00006464 [C3070000]              	dd	irq10
  2244 00006468 [C7070000]              	dd	irq11
  2245 0000646C [CB070000]              	dd	irq12
  2246 00006470 [CF070000]              	dd	irq13
  2247                                  ;HDISK_INT1:  ;06/02/2015 	
  2248 00006474 [8D2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2249                                  		;dd	irq14
  2250                                  ;HDISK_INT2:  ;06/02/2015
  2251 00006478 [B02D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2252                                  		;dd	irq15	; INT 2Fh
  2253                                  		; 14/08/2015
  2254 0000647C [E3390000]              	dd	sysent		; INT 30h (system calls)
  2255                                  	
  2256                                  	;dd	ignore_int
  2257 00006480 00000000                	dd	0
  2258                                  
  2259                                  ;;;
  2260                                  ;;; 11/03/2015
  2261                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2262                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2263                              <1> ; Last Modification: 11/03/2015
  2264                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2265                              <1> ;
  2266                              <1> ; ///////// KEYBOARD DATA ///////////////
  2267                              <1> 
  2268                              <1> ; 05/12/2014
  2269                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2270                              <1> ; 03/06/86  KEYBOARD BIOS
  2271                              <1> 
  2272                              <1> ;---------------------------------------------------------------------------------
  2273                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2274                              <1> ;---------------------------------------------------------------------------------
  2275                              <1> 
  2276                              <1> ;-----	TABLES FOR ALT CASE ------------
  2277                              <1> ;-----	ALT-INPUT-TABLE 
  2278 00006484 524F50514B          <1> K30:	db	82,79,80,81,75
  2279 00006489 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2280                              <1> ;-----	SUPER-SHIFT-TABLE 
  2281 0000648E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2282 00006494 161718191E1F        <1> 	db	22,23,24,25,30,31
  2283 0000649A 202122232425        <1> 	db	32,33,34,35,36,37
  2284 000064A0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2285 000064A6 3132                <1> 	db	49,50
  2286                              <1> 
  2287                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2288                              <1> ;-----	KEY_TABLE 
  2289 000064A8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2290 000064A9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2291 000064AE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2292                              <1> _K6L    equ     $-_K6
  2293                              <1> 
  2294                              <1> ;-----	MASK_TABLE
  2295 000064B0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2296 000064B1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2297 000064B6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2298                              <1> 
  2299                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2300 000064B8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2301 000064BE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2302 000064C4 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2303 000064CA 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2304 000064D0 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2305 000064D6 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2306 000064DC 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2307 000064E2 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2308 000064E8 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2309 000064EE 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2310                              <1> 	;				;----- FUNCTIONS ------		
  2311 000064F2 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2312 000064F8 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2313 000064FE 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2314 00006504 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2315 0000650A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2316                              <1> 
  2317                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2318 00006510 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2318 00006519 39302D3D0809        <1>
  2319 0000651F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2319 00006528 705B5D0DFF61736466- <1>
  2319 00006531 67686A6B6C3B27      <1>
  2320 00006538 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2320 00006541 6D2C2E2FFF2AFF20FF  <1>
  2321                              <1> ;-----	LC TABLE SCAN
  2322 0000654A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2323 0000654F 4041424344          <1> 	db	64,65,66,67,68
  2324 00006554 FFFF                <1> 	db	-1,-1			; NL, SL
  2325                              <1> 
  2326                              <1> ;-----	KEYPAD TABLE
  2327 00006556 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2328 0000655C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2329 00006563 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2330                              <1> 
  2331                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2332 00006568 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2332 00006571 28295F2B0800        <1>
  2333 00006577 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2333 00006580 507B7D0DFF41534446- <1>
  2333 00006589 47484A4B4C3A22      <1>
  2334 00006590 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2334 00006599 4D3C3E3FFF2AFF20FF  <1>
  2335                              <1> ;-----	UC TABLE SCAN
  2336 000065A2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2337 000065A7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2338 000065AC FFFF                <1> 	db	-1,-1			; NL, SL
  2339                              <1> 
  2340                              <1> ;-----	NUM STATE TABLE
  2341 000065AE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2341 000065B7 3233302E            <1>
  2342                              <1> 	;
  2343 000065BB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2344                              <1> 
  2345                              <1> Align	4
  2346                              <1> ;----------------------------------------
  2347                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2348                              <1> ;----------------------------------------
  2349 000065C0 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2350 000065C1 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2351                              <1> 				; (29h default setting for video mode 3)
  2352                              <1> 				; Mode Select register Bits
  2353                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2354                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2355                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2356                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2357                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2358                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2359                              <1> 				;   BIT 6, 7 - Not Used
  2360                              <1> 
  2361                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2362                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2363                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2364                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2365                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2366                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2367                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2368                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2369                              <1> ; Mode & 37h = Video signal OFF
  2370                              <1> 			
  2371                              <1> 
  2372                              <1> ; 26/08/2014
  2373                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2374                              <1> ; Derived from IBM "pc-at" 
  2375                              <1> ; rombios source code (06/10/1985)
  2376                              <1> ; 'dseg.inc'
  2377                              <1> 
  2378                              <1> ;---------------------------------------;
  2379                              <1> ;	SYSTEM DATA AREA		;
  2380                              <1> ;----------------------------------------
  2381 000065C2 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2382                              <1> 
  2383                              <1> ;----------------------------------------
  2384                              <1> ;	KEYBOARD DATA AREAS		;
  2385                              <1> ;----------------------------------------
  2386                              <1> 
  2387 000065C3 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2388 000065C4 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2389 000065C5 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2390 000065C6 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2391 000065C7 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2392 000065C8 [D8650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2393 000065CC [F8650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2394 000065D0 [D8650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2395 000065D4 [D8650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2396                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2397 000065D8 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2398                              <1> 
  2399                              <1> ; /// End Of KEYBOARD DATA ///
  2262                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2263                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2264                              <1> ; Last Modification: 11/03/2015
  2265                              <1> ;		    (Data section for 'VIDEO.INC')	
  2266                              <1> ;
  2267                              <1> ; ///////// VIDEO DATA ///////////////
  2268                              <1> 
  2269                              <1> video_params:
  2270                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2271                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2272                              <1> 	; VIDEO MODE 3
  2273 000065F8 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2274 000065FF 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2275 00006604 00000000            <1> 	db	0,0,0,0
  2276                              <1> 
  2277                              <1> ; /// End Of VIDEO DATA ///
  2263                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2264                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2265                              <1> ; Last Modification: 11/03/2015
  2266                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2267                              <1> ;
  2268                              <1> ; *****************************************************************************
  2269                              <1> 
  2270                              <1> ;----------------------------------------
  2271                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2272                              <1> ;	REFERENCED BY POST & BIOS	:
  2273                              <1> ;----------------------------------------
  2274                              <1> 
  2275 00006608 [6B660000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2276                              <1> 
  2277                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2278                              <1> ;----------------------------------------------------------------
  2279                              <1> ; DISK_BASE							:
  2280                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2281                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2282                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2283                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2284                              <1> ;----------------------------------------------------------------
  2285                              <1> 
  2286                              <1> ;DISK_BASE:	
  2287                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2288                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2289                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2290                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2291                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2292                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2293                              <1> ;	DB	01BH		; GAP LENGTH
  2294                              <1> ;	DB	0FFH		; DTL
  2295                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2296                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2297                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2298                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2299                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2300                              <1> 
  2301                              <1> ;----------------------------------------
  2302                              <1> ;	ROM BIOS DATA AREAS		:
  2303                              <1> ;----------------------------------------
  2304                              <1> 
  2305                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2306                              <1> 
  2307                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2308                              <1> 
  2309                              <1> ;----------------------------------------
  2310                              <1> ;	DISKETTE DATA AREAS		:
  2311                              <1> ;----------------------------------------
  2312                              <1> 
  2313                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2314                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2315                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2316                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2317                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2318                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2319                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2320                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2321                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2322                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2323                              <1> 
  2324                              <1> ;----------------------------------------
  2325                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2326                              <1> ;----------------------------------------
  2327                              <1> 
  2328                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2329                              <1> 
  2330                              <1> ;----------------------------------------
  2331                              <1> ;	TIMER DATA AREA 		:
  2332                              <1> ;----------------------------------------
  2333                              <1> 
  2334                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2335                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2336                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2337                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2338                              <1> 
  2339                              <1> ;----------------------------------------
  2340                              <1> ;	ADDITIONAL MEDIA DATA		:
  2341                              <1> ;----------------------------------------
  2342                              <1> 
  2343                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2344                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2345                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2346                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2347                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2348                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2349                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2350                              <1> 
  2351                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2352                              <1> 
  2353                              <1> ;--------------------------------------------------------
  2354                              <1> ;	DRIVE TYPE TABLE				:
  2355                              <1> ;--------------------------------------------------------
  2356                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2357                              <1> DR_TYPE:
  2358 0000660C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2359                              <1>                 ;DW      MD_TBL1
  2360 0000660D [2A660000]          <1> 		dd	MD_TBL1
  2361 00006611 82                  <1> 		DB	02+BIT7ON
  2362                              <1> 		;DW      MD_TBL2
  2363 00006612 [37660000]          <1>                 dd      MD_TBL2
  2364 00006616 02                  <1> DR_DEFAULT:	DB	02
  2365                              <1>                 ;DW      MD_TBL3
  2366 00006617 [44660000]          <1> 		dd      MD_TBL3
  2367 0000661B 03                  <1> 		DB	03
  2368                              <1>                 ;DW      MD_TBL4
  2369 0000661C [51660000]          <1> 		dd      MD_TBL4
  2370 00006620 84                  <1> 		DB	04+BIT7ON
  2371                              <1>                 ;DW      MD_TBL5
  2372 00006621 [5E660000]          <1> 		dd      MD_TBL5
  2373 00006625 04                  <1> 		DB	04
  2374                              <1>                 ;DW      MD_TBL6
  2375 00006626 [6B660000]          <1> 		dd      MD_TBL6
  2376                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2377                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2378                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2379                              <1> ;--------------------------------------------------------
  2380                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2381                              <1> ;--------------------------------------------------------
  2382                              <1> ;--------------------------------------------------------
  2383                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2384                              <1> ;--------------------------------------------------------
  2385                              <1> MD_TBL1:        
  2386 0000662A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2387 0000662B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2388 0000662C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2389 0000662D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2390 0000662E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2391 0000662F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2392 00006630 FF                  <1> 	DB	0FFH		; DTL
  2393 00006631 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2394 00006632 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2395 00006633 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2396 00006634 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2397 00006635 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2398 00006636 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2399                              <1> ;--------------------------------------------------------
  2400                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2401                              <1> ;--------------------------------------------------------
  2402                              <1> MD_TBL2:        
  2403 00006637 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2404 00006638 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2405 00006639 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2406 0000663A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2407 0000663B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2408 0000663C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2409 0000663D FF                  <1> 	DB	0FFH		; DTL
  2410 0000663E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2411 0000663F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2412 00006640 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2413 00006641 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2414 00006642 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2415 00006643 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2416                              <1> ;--------------------------------------------------------
  2417                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2418                              <1> ;--------------------------------------------------------
  2419                              <1> MD_TBL3:
  2420 00006644 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2421 00006645 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2422 00006646 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2423 00006647 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2424 00006648 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2425 00006649 1B                  <1> 	DB	01BH		; GAP LENGTH
  2426 0000664A FF                  <1> 	DB	0FFH		; DTL
  2427 0000664B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2428 0000664C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2429 0000664D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2430 0000664E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2431 0000664F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2432 00006650 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2433                              <1> ;--------------------------------------------------------
  2434                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2435                              <1> ;--------------------------------------------------------
  2436                              <1> MD_TBL4:
  2437 00006651 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2438 00006652 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2439 00006653 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2440 00006654 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2441 00006655 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2442 00006656 2A                  <1> 	DB	02AH		; GAP LENGTH
  2443 00006657 FF                  <1> 	DB	0FFH		; DTL
  2444 00006658 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2445 00006659 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2446 0000665A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2447 0000665B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2448 0000665C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2449 0000665D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2450                              <1> ;--------------------------------------------------------
  2451                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2452                              <1> ;--------------------------------------------------------
  2453                              <1> MD_TBL5:
  2454 0000665E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2455 0000665F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2456 00006660 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2457 00006661 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2458 00006662 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2459 00006663 2A                  <1> 	DB	02AH		; GAP LENGTH
  2460 00006664 FF                  <1> 	DB	0FFH		; DTL
  2461 00006665 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2462 00006666 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2463 00006667 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2464 00006668 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2465 00006669 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2466 0000666A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2467                              <1> ;--------------------------------------------------------
  2468                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2469                              <1> ;--------------------------------------------------------
  2470                              <1> MD_TBL6:
  2471 0000666B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2472 0000666C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2473 0000666D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2474 0000666E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2475 0000666F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2476 00006670 1B                  <1> 	DB	01BH		; GAP LENGTH
  2477 00006671 FF                  <1> 	DB	0FFH		; DTL
  2478 00006672 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2479 00006673 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2480 00006674 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2481 00006675 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2482 00006676 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2483 00006677 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2484                              <1> 
  2485                              <1> 
  2486                              <1> ; << diskette.inc >>
  2487                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2488                              <1> ;
  2489                              <1> ;----------------------------------------
  2490                              <1> ;	ROM BIOS DATA AREAS		:
  2491                              <1> ;----------------------------------------
  2492                              <1> 
  2493                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2494                              <1> 
  2495                              <1> ;----------------------------------------
  2496                              <1> ;	FIXED DISK DATA AREAS		:
  2497                              <1> ;----------------------------------------
  2498                              <1> 
  2499                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2500                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2501                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2502                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2503                              <1> 
  2504                              <1> ;----------------------------------------
  2505                              <1> ;	ADDITIONAL MEDIA DATA		:
  2506                              <1> ;----------------------------------------
  2507                              <1> 
  2508                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2509                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2510                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2511                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2512                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2513                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2514                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2515                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2516                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2517                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2518                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2519                              <1> 
  2520                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2521                              <1> ;
  2522                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2523                              <1> 
  2524                              <1> ERR_TBL:
  2525 00006678 E0                  <1> 	db	NO_ERR
  2526 00006679 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2527 0000667D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2528                              <1> 
  2529                              <1> ; 17/12/2014 (mov ax, [cfd])
  2530                              <1> ; 11/12/2014
  2531 00006681 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2532                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2533 00006682 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2534                              <1> 					; (initial value of 'pfd 
  2535                              <1> 					; must be different then 'cfd' value
  2536                              <1> 					; to force updating/initializing
  2537                              <1> 					; current drive parameters) 
  2538 00006683 90                  <1> align 2
  2539                              <1> 
  2540 00006684 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2541                              <1> 			      ; (170h)
  2542 00006686 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2543                              <1> 
  2544                              <1> ; 05/01/2015 
  2545 00006688 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2546                              <1> 
  2547                              <1> ; *****************************************************************************
  2264                                  ;;;
  2265                                  
  2266 00006689 90                      Align 2
  2267                                  
  2268                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2269 0000668A 00                      boot_drv:    db 0 ; boot drive number (physical)
  2270                                  ; 24/11/2014
  2271 0000668B 00                      drv:	     db 0 
  2272 0000668C 00                      last_drv:    db 0 ; last hdd
  2273 0000668D 00                      hdc:         db 0  ; number of hard disk drives
  2274                                  		     ; (present/detected)
  2275                                  ;
  2276                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2277                                  ; Physical drive type & flags
  2278 0000668E 00                      fd0_type:    db 0  ; floppy drive type
  2279 0000668F 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2280                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2281                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2282                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2283                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2284 00006690 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2285 00006691 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2286 00006692 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2287 00006693 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2288                                  		     ; bit 0 - Fixed disk access subset supported
  2289                                  		     ; bit 1 - Drive locking and ejecting
  2290                                  		     ; bit 2 - Enhanced disk drive support
  2291                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2292                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2293                                  		     ; will interpret it as 'LBA ready'!)		
  2294                                  
  2295                                  ; 11/03/2015 - 10/07/2015
  2296 00006694 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2296 0000669D 0000000000         
  2297 000066A2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2297 000066AB 0000000000         
  2298 000066B0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2298 000066B9 0000000000         
  2299 000066BE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2299 000066C7 000000000000000000-
  2299 000066D0 000000000000000000-
  2299 000066D9 00                 
  2300 000066DA 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2301 000066E1 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2302                                  ;
  2303                                  
  2304                                  ; 27/08/2014
  2305                                  scr_row:
  2306 000066E8 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2307                                  scr_col:
  2308 000066EC 00000000                	dd 0
  2309                                  
  2310                                  ;; 14/08/2015
  2311                                  ;;msgPM:
  2312                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2313                                  msgKVER:
  2314                                  	;;db "Retro UNIX 386 v1 - Kernel v0.2.0.17 [04/02/2016]", 0
  2315                                  	;db "Retro UNIX 386 v1 - Kernel v0.2.0.18 [29/04/2022]", 0	
  2316 000066F0 526574726F20554E49-     	db "Retro UNIX 386 v1 - Kernel v0.2.0.19 [02/06/2022]", 0
  2316 000066F9 582033383620763120-
  2316 00006702 2D204B65726E656C20-
  2316 0000670B 76302E322E302E3139-
  2316 00006714 205B30322F30362F32-
  2316 0000671D 3032325D00         
  2317                                  
  2318                                  Align 2
  2319                                  
  2320                                  ; 20/08/2014
  2321                                    ; /* This is the default interrupt "handler" :-) */ 
  2322                                    ; Linux v0.12 (head.s)
  2323                                  int_msg:
  2324 00006722 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2324 0000672B 6E7465727275707420-
  2324 00006734 212000             
  2325                                  
  2326 00006737 90                      Align 2  
  2327                                  
  2328                                  ; 21/08/2014
  2329                                  timer_msg:
  2330 00006738 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2330 00006741 542032306829202120-
  2330 0000674A 54696D657220496E74-
  2330 00006753 657272757074203A20 
  2331                                  tcountstr:
  2332 0000675C 303030303020            	db "00000 "
  2333 00006762 00                      	db 0
  2334                                  
  2335 00006763 90                      Align 2
  2336                                  	; 21/08/2014
  2337                                  exc_msg:
  2338 00006764 435055206578636570-     	db "CPU exception ! "
  2338 0000676D 74696F6E202120     
  2339                                  excnstr: 		; 25/08/2014
  2340 00006774 3F3F68202045495020-     	db "??h", "  EIP : "
  2340 0000677D 3A20               
  2341                                  EIPstr: ; 29/08/2014
  2342 0000677F 00<rep Ch>              	times 12 db 0
  2343                                  rtc_msg:
  2344 0000678B 5265616C2054696D65-     	db "Real Time Clock - "
  2344 00006794 20436C6F636B202D20 
  2345                                  datestr:
  2346 0000679D 30302F30302F303030-     	db "00/00/0000"
  2346 000067A6 30                 
  2347 000067A7 20                      	db " "
  2348                                  daystr:
  2349 000067A8 44415920                	db "DAY "
  2350                                  timestr:	
  2351 000067AC 30303A30303A3030                db "00:00:00"
  2352 000067B4 20                      	db " "
  2353 000067B5 00                      	db 0 
  2354                                  
  2355                                  daytmp:
  2356                                  	; 28/02/2015
  2357 000067B6 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2357 000067BF 4F4E20545545205745-
  2357 000067C8 442054485520465249-
  2357 000067D1 2053415420         
  2358                                  
  2359 000067D6 FF                      ptime_seconds: db 0FFh
  2360                                  
  2361                                  	; 23/02/2015
  2362                                  	; 25/08/2014
  2363                                  ;scounter:
  2364                                  ;	db 5
  2365                                  ;	db 19
  2366                                  
  2367                                  ;; 05/11/2014
  2368                                  ;msg_out_of_memory:
  2369                                  ;	db 	07h, 0Dh, 0Ah
  2370                                  ;	db      'Insufficient memory ! '
  2371                                  ;	db	'(Minimum 2 MB memory is needed.)'
  2372                                  ; 	db	0Dh, 0Ah, 0
  2373                                  	;
  2374                                  setup_error_msg:
  2375 000067D7 0D0A                    	db 0Dh, 0Ah
  2376 000067D9 4469736B2053657475-     	db 'Disk Setup Error!' 
  2376 000067E2 70204572726F7221   
  2377 000067EA 0D0A00                  	db 0Dh, 0Ah,0
  2378                                  
  2379                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2380                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2381                                  ;	  db 0 ; upper left row (for scroll)	
  2382                                  
  2383                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2384                                  ;	  db 24 ; lower right row (for scroll)
  2385                                  
  2386                                  
  2387                                  ; 06/11/2014 (Temporary Data)
  2388                                  ; Memory Information message
  2389                                  ; 14/08/2015
  2390                                  msg_memory_info:
  2391 000067ED 07                      	db	07h
  2392 000067EE 0D0A                    	db	0Dh, 0Ah
  2393                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2394 000067F0 546F74616C206D656D-     	db	"Total memory : "
  2394 000067F9 6F7279203A20       
  2395                                  mem_total_b_str: ; 10 digits
  2396 000067FF 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2396 00006808 302062797465730D0A 
  2397 00006811 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2397 0000681A 202020202020202020 
  2398                                  mem_total_p_str: ; 7 digits
  2399 00006823 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2399 0000682C 616765730D0A       
  2400 00006832 0D0A                    	db 	0Dh, 0Ah
  2401 00006834 46726565206D656D6F-     	db	"Free memory  : "
  2401 0000683D 727920203A20       
  2402                                  free_mem_b_str:  ; 10 digits
  2403 00006843 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2403 0000684C 3F2062797465730D0A 
  2404 00006855 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2404 0000685E 202020202020202020 
  2405                                  free_mem_p_str:  ; 7 digits
  2406 00006867 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2406 00006870 616765730D0A       
  2407 00006876 0D0A00                  	db	0Dh, 0Ah, 0
  2408                                  
  2409                                  dsk_ready_msg:
  2410 00006879 0D0A                    	db 	0Dh, 0Ah
  2411                                  dsktype:
  2412 0000687B 6664                    	db	'fd'
  2413                                  dskx:
  2414 0000687D 30                      	db	'0'
  2415 0000687E 20                      	db	20h
  2416 0000687F 697320524541445920-     	db 	'is READY ...'
  2416 00006888 2E2E2E             
  2417 0000688B 00                      	db 	0
  2418                                  nextline:
  2419 0000688C 0D0A00                  	db 	0Dh, 0Ah, 0
  2420                                  
  2421                                  ; KERNEL - SYSINIT Messages
  2422                                  ; 24/08/2015
  2423                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2424                                  ; 14/07/2013
  2425                                  ;kernel_init_err_msg:
  2426                                  ;	db 0Dh, 0Ah
  2427                                  ;	db 07h
  2428                                  ;	db 'Kernel initialization ERROR !'
  2429                                  ;	db 0Dh, 0Ah, 0 
  2430                                  ; 24/08/2015
  2431                                  ;;; (temporary kernel init message has been removed
  2432                                  ;;;  from 'sys_init' code)
  2433                                  ;kernel_init_ok_msg: 
  2434                                  ;	db 0Dh, 0Ah
  2435                                  ;	db 07h
  2436                                  ;	db 'Welcome to Retro UNIX 386 v1 Operating System !'
  2437                                  ;	db 0Dh, 0Ah
  2438                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.0.17)'
  2439                                  ;	db 0Dh, 0Ah, 0
  2440                                  panic_msg:
  2441 0000688F 0D0A07                  	db 0Dh, 0Ah, 07h
  2442 00006892 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2442 0000689B 726E656C2050616E69-
  2442 000068A4 632021             
  2443 000068A7 0D0A00                  	db 0Dh, 0Ah, 0
  2444                                  etc_init_err_msg:
  2445 000068AA 0D0A                    	db 0Dh, 0Ah
  2446 000068AC 07                      	db 07h
  2447 000068AD 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2447 000068B6 74632F696E69742021-
  2447 000068BF 3F                 
  2448 000068C0 0D0A00                  	db 0Dh, 0Ah, 0
  2449                                  
  2450                                  ; 10/05/2015
  2451                                  badsys_msg:
  2452 000068C3 0D0A                    	db 0Dh, 0Ah
  2453 000068C5 07                      	db 07h
  2454 000068C6 496E76616C69642053-     	db 'Invalid System Call !'
  2454 000068CF 797374656D2043616C-
  2454 000068D8 6C2021             
  2455 000068DB 0D0A                    	db 0Dh, 0Ah
  2456 000068DD 4541583A20              	db 'EAX: '
  2457                                  bsys_msg_eax:
  2458 000068E2 303030303030303068      	db '00000000h'
  2459 000068EB 0D0A                    	db 0Dh, 0Ah
  2460 000068ED 4549503A20              	db 'EIP: '
  2461                                  bsys_msg_eip:
  2462 000068F2 303030303030303068      	db '00000000h' 
  2463 000068FB 0D0A00                  	db 0Dh, 0Ah, 0
  2464                                  
  2465                                  BSYS_M_SIZE equ $ - badsys_msg
  2466                                  
  2467                                  
  2468                                  align 2
  2469                                  
  2470                                  ; EPOCH Variables
  2471                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2472                                  ; 09/04/2013 epoch variables
  2473                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2474                                  ;
  2475 000068FE B207                    year: 	dw 1970
  2476                                  ;month: dw 1
  2477                                  ;day: 	dw 1
  2478                                  ;hour: 	dw 0
  2479                                  ;minute: dw 0
  2480                                  ;second: dw 0
  2481                                  ; 02/06/2022
  2482 00006900 01                      month:	db 1
  2483 00006901 01                      day:	db 1
  2484 00006902 01                      hour:	db 1
  2485 00006903 01                      minute: db 1
  2486 00006904 01                      second:	db 1
  2487 00006905 01                      	db 1
  2488                                  
  2489                                  DMonth:
  2490 00006906 0000                    	dw 0
  2491 00006908 1F00                    	dw 31
  2492 0000690A 3B00                    	dw 59
  2493 0000690C 5A00                    	dw 90
  2494 0000690E 7800                    	dw 120
  2495 00006910 9700                    	dw 151
  2496 00006912 B500                    	dw 181
  2497 00006914 D400                    	dw 212
  2498 00006916 F300                    	dw 243
  2499 00006918 1101                    	dw 273
  2500 0000691A 3001                    	dw 304
  2501 0000691C 4E01                    	dw 334
  2502                                  
  2503                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2504 0000691E 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2505                                                       ; 1 and 16 MB, max. 3C00h = 15 MB.
  2506 00006920 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2507                                  		   ;   between 16 MB and 4 GB.
  2508                                  
  2509 00006922 90<rep Eh>              align 16
  2510                                  
  2511                                  bss_start:
  2512                                  
  2513                                  ABSOLUTE bss_start
  2514                                  
  2515                                  	; 11/03/2015
  2516                                  	; Interrupt Descriptor Table (20/08/2014)
  2517                                  idt:
  2518 00006930 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2519                                  idt_end:
  2520                                  
  2521                                  ;alignb 4
  2522                                  
  2523                                  task_state_segment:
  2524                                  	; 24/03/2015
  2525 00006B30 ????                    tss.link:   resw 1
  2526 00006B32 ????                    	    resw 1
  2527                                  ; tss offset 4	
  2528 00006B34 ????????                tss.esp0:   resd 1
  2529 00006B38 ????                    tss.ss0:    resw 1
  2530 00006B3A ????                    	    resw 1	
  2531 00006B3C ????????                tss.esp1:   resd 1
  2532 00006B40 ????                    tss.ss1:    resw 1
  2533 00006B42 ????                    	    resw 1 	
  2534 00006B44 ????????                tss.esp2:   resd 1
  2535 00006B48 ????                    tss.ss2:    resw 1
  2536 00006B4A ????                    	    resw 1
  2537                                  ; tss offset 28
  2538 00006B4C ????????                tss.CR3:    resd 1
  2539 00006B50 ????????                tss.eip:    resd 1
  2540 00006B54 ????????                tss.eflags: resd 1
  2541                                  ; tss offset 40
  2542 00006B58 ????????                tss.eax:    resd 1		 		
  2543 00006B5C ????????                tss.ecx:    resd 1
  2544 00006B60 ????????                tss.edx:    resd 1
  2545 00006B64 ????????                tss.ebx:    resd 1
  2546 00006B68 ????????                tss.esp:    resd 1
  2547 00006B6C ????????                tss.ebp:    resd 1
  2548 00006B70 ????????                tss.esi:    resd 1
  2549 00006B74 ????????                tss.edi:    resd 1
  2550                                  ; tss offset 72
  2551 00006B78 ????                    tss.ES:     resw 1
  2552 00006B7A ????                    	    resw 1	
  2553 00006B7C ????                    tss.CS:	    resw 1
  2554 00006B7E ????                    	    resw 1
  2555 00006B80 ????                    tss.SS:	    resw 1
  2556 00006B82 ????                    	    resw 1
  2557 00006B84 ????                    tss.DS:	    resw 1
  2558 00006B86 ????                    	    resw 1
  2559 00006B88 ????                    tss.FS:	    resw 1
  2560 00006B8A ????                    	    resw 1
  2561 00006B8C ????                    tss.GS:	    resw 1
  2562 00006B8E ????                    	    resw 1		
  2563 00006B90 ????                    tss.LDTR:   resw 1
  2564 00006B92 ????                    	    resw 1
  2565                                  ; tss offset 100		
  2566 00006B94 ????                    	    resw 1		
  2567 00006B96 ????                    tss.IOPB:   resw 1
  2568                                  ; tss offset 104 
  2569                                  tss_end:
  2570                                  
  2571 00006B98 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2572                                  		    ; (Physical address = Virtual address)	 	
  2573 00006B9C ????????                memory_size: resd 1 ; memory size in pages
  2574 00006BA0 ????????                free_pages:  resd 1 ; number of free pages		
  2575 00006BA4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2576                                  		    ; first free page search
  2577 00006BA8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2578                                  		    ; next free page search will be
  2579                                  		    ; stopped after it. (end of M.A.T.)
  2580 00006BAC ????????                first_page:  resd 1 ; offset value in M.A.T. which
  2581                                  		    ; first free page search
  2582                                  		    ; will be started on it. (for user)
  2583 00006BB0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2584                                  
  2585                                  ;;;
  2586                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2587                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2588 00006BB4 ????                    CRT_START:   resw 1 ; starting address in regen buffer
  2589                                  		    ; NOTE: active page only
  2590 00006BB6 <res 10h>               cursor_posn: resw 8 ; cursor positions for video pages
  2591                                  active_page: 
  2592 00006BC6 ??                      ptty: 	     resb 1 ; current tty
  2593                                  ; 01/07/2015
  2594 00006BC7 ??                      ccolor:	     resb 1 ; current color attributes ('sysmsg')	
  2595                                  ; 26/10/2015
  2596                                  ; 07/09/2014
  2597 00006BC8 <res 14h>               ttychr:      resw ntty+2 ; Character buffer (multiscreen)
  2598                                  
  2599                                  ; 21/08/2014
  2600 00006BDC ????????                tcount:	     resd 1
  2601                                  
  2602                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2603 00006BE0 ????????                p_time:      resd 1 ; present time (for systime & sysmdate)
  2604                                  
  2605                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2606                                  ; (open mode locks for pseudo TTYs)
  2607                                  ; [ major tty locks (return error in any conflicts) ]
  2608 00006BE4 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2609                                  
  2610                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2611                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2612 00006BF8 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2613                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2614                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2615                                  ;; 0 means serial port is not available 
  2616                                  ;;comprm: ; 25/06/2014
  2617 00006C02 ??                      com1p:       resb 1 ;;0E3h
  2618 00006C03 ??                      com2p:       resb 1 ;;0E3h
  2619                                  
  2620                                  ; 17/11/2015
  2621                                  ; request for response (from the terminal)	
  2622 00006C04 ????                    req_resp:     resw 1 			
  2623                                  ; 07/11/2015
  2624 00006C06 ??                      ccomport:    resb 1 ; current COM (serial) port
  2625                                  		    ; (0= COM1, 1= COM2)
  2626                                  ; 09/11/2015
  2627 00006C07 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2628                                  ; 07/11/2015
  2629 00006C08 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2630 00006C0A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2631                                  
  2632                                  ; 23/10/2015
  2633                                  ; SERIAL PORTS - COMMUNICATION MODES
  2634                                  ; (Retro UNIX 386 v1 feature only!)
  2635                                  ; 0 - command mode (default/initial mode)
  2636                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2637                                  ;;; communication modes for future versions:  
  2638                                  ; // 2 - keyboard mode (ascii+scancode input)
  2639                                  ; // 3 - mouse mode
  2640                                  ; // 4 - device control (output) mode
  2641                                  ; VALID COMMANDS for current version:
  2642                                  ; 	'LOGIN'
  2643                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2644                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2645                                  ;  Login response: db 0FFh, 'login', 0
  2646                                  ;	 ("login request accepted, wait for login prompt") 
  2647                                  ; When a login requests is received and acknowledged (by
  2648                                  ; serial port interrupt handler (communication procedure),
  2649                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2650                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2651                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2652                                  ; 
  2653                                  ; 'sys connect' system call is used to change communication mode
  2654                                  ; except 'LOGIN' command which is used to start terminal mode
  2655                                  ; by using (COM port) terminal.
  2656                                  
  2657                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2658                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2659                                  ;com1mode:    resb 1 ; communication mode for COM1
  2660                                  ;com1com:     resb 1 ; communication command for COM1
  2661                                  ;com2mode:    resb 1 ; communication mode for COM1
  2662                                  ;com2com      resb 1 ; communication command for COM1
  2663                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2664                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2665                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2666                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2667                                  
  2668                                  ; 22/08/2014 (RTC)
  2669                                  ; (Packed BCD)
  2670 00006C0C ??                      time_seconds: resb 1
  2671 00006C0D ??                      time_minutes: resb 1
  2672 00006C0E ??                      time_hours:   resb 1
  2673 00006C0F ??                      date_wday:    resb 1
  2674 00006C10 ??                      date_day:     resb 1
  2675 00006C11 ??                      date_month:   resb 1			
  2676 00006C12 ??                      date_year:    resb 1
  2677 00006C13 ??                      date_century: resb 1
  2678                                  
  2679                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2680                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2681                              <1> ; Last Modification: 10/07/2015
  2682                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2683                              <1> ;
  2684                              <1> ; *****************************************************************************
  2685                              <1> 
  2686                              <1> alignb 2
  2687                              <1> 
  2688                              <1> ;----------------------------------------
  2689                              <1> ;	TIMER DATA AREA 		:
  2690                              <1> ;----------------------------------------
  2691                              <1> 
  2692                              <1> TIMER_LH:	; 16/02/205
  2693 00006C14 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2694 00006C16 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2695 00006C18 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2696                              <1> 
  2697                              <1> ;----------------------------------------
  2698                              <1> ;	DISKETTE DATA AREAS		:
  2699                              <1> ;----------------------------------------
  2700                              <1> 
  2701 00006C19 ??                  <1> SEEK_STATUS:	resb	1
  2702 00006C1A ??                  <1> MOTOR_STATUS:	resb	1
  2703 00006C1B ??                  <1> MOTOR_COUNT:	resb	1
  2704 00006C1C ??                  <1> DSKETTE_STATUS:	resb	1
  2705 00006C1D ??????????????      <1> NEC_STATUS:	resb	7
  2706                              <1> 
  2707                              <1> ;----------------------------------------
  2708                              <1> ;	ADDITIONAL MEDIA DATA		:
  2709                              <1> ;----------------------------------------
  2710                              <1> 
  2711 00006C24 ??                  <1> LASTRATE:	resb 	1
  2712 00006C25 ??                  <1> HF_STATUS:	resb 	1
  2713 00006C26 ??                  <1> HF_ERROR:	resb 	1
  2714 00006C27 ??                  <1> HF_INT_FLAG:	resb 	1
  2715 00006C28 ??                  <1> HF_CNTRL:	resb 	1
  2716 00006C29 ????????            <1> DSK_STATE:	resb 	4
  2717 00006C2D ????                <1> DSK_TRK:	resb 	2
  2718                              <1> 
  2719                              <1> ;----------------------------------------
  2720                              <1> ;	FIXED DISK DATA AREAS		:
  2721                              <1> ;----------------------------------------
  2722                              <1> 
  2723 00006C2F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2724 00006C30 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2725 00006C31 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2726                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2727                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2728                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2729                              <1> 
  2730 00006C32 ????                <1> alignb 4
  2731                              <1> 
  2732                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2733                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2734                              <1> HF_TBL_VEC: ; 22/12/2014	
  2735 00006C34 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2736 00006C38 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2737 00006C3C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2738 00006C40 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2739                              <1> 
  2740                              <1> ; 03/01/2015
  2741 00006C44 ??                  <1> LBAMode:     	resb	1
  2742                              <1> 
  2743                              <1> ; *****************************************************************************
  2680                                  
  2681                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2682                                  
  2683                                  ;alignb 2
  2684                                  
  2685                                  ; 27/02/2022
  2686                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2687                                  
  2688                                  ; 23/02/2022
  2689                                  ;; Memory (swap) Data (11/03/2015)
  2690                                  ; 09/03/2015
  2691                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2692                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2693                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  2694                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2695                                  ;swpd_next:  resd 1 ; next free page block
  2696                                  ;swpd_last:  resd 1 ; last swap page block	
  2697                                  
  2698 00006C45 ??????                  alignb 4
  2699                                  
  2700                                  ; 10/07/2015
  2701                                  ; 28/08/2014
  2702 00006C48 ????????                error_code:	resd 1
  2703                                  ; 29/08/2014
  2704 00006C4C ????????                FaultOffset: 	resd 1
  2705                                  ; 21/09/2015
  2706 00006C50 ????????                PF_Count:	resd 1	; total page fault count
  2707                                  		       	; (for debugging - page fault analyze)
  2708                                  		 	; 'page _fault_handler' (memory.inc)
  2709                                  			; 'sysgeterr' (u9.s)
  2710                                  ; 23/02/2022
  2711 00006C54 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2712                                  			;  for a system call in next retro unix 386 version)
  2713                                  			; -2 ticks per second-
  2714                                  ;; 21/08/2015
  2715                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2716                                  
  2717                                  ; 27/02/2022
  2718                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2719                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.0.19) - SYSX.INC (ux.s)
  2720                              <1> ; Last Modification: 14/05/2022
  2721                              <1> ;
  2722                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2723                              <1> ; (Modified from 
  2724                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2725                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2726                              <1> ; ----------------------------------------------------------------------------
  2727                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2728                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2729                              <1> ; <Bell Laboratories (17/3/1972)>
  2730                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2731                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2732                              <1> ; ****************************************************************************
  2733                              <1> ; 13/11/2015
  2734                              <1> 
  2735                              <1> alignb 2
  2736                              <1> 
  2737                              <1> inode:
  2738                              <1> 	; 11/03/2013. 
  2739                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2740                              <1> 	;i.
  2741                              <1> 
  2742 00006C58 ????                <1> 	i.flgs:	 resw 1
  2743 00006C5A ??                  <1> 	i.nlks:	 resb 1
  2744 00006C5B ??                  <1> 	i.uid:	 resb 1
  2745 00006C5C ????                <1>         i.size:  resw 1 ; size
  2746 00006C5E <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2747 00006C6E ????????            <1> 	i.ctim:	 resd 1
  2748 00006C72 ????????            <1> 	i.mtim:	 resd 1
  2749 00006C76 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2750                              <1> 
  2751                              <1> I_SIZE	equ $ - inode 
  2752                              <1> 
  2753                              <1> process:
  2754                              <1> 	; 26/02/2022
  2755                              <1> 	; 04/02/2022
  2756                              <1> 	; 06/05/2015
  2757                              <1> 	; 11/03/2013 - 05/02/2014
  2758                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2759                              <1> 	;p.
  2760                              <1> 	
  2761 00006C78 <res 20h>           <1>         p.pid:   resw nproc
  2762 00006C98 <res 20h>           <1>         p.ppid:  resw nproc
  2763                              <1>         ;p.break: resw nproc ; 04/02/2022 (p.break is not used)
  2764 00006CB8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2765                              <1> 	; 26/02/2022 (p.waitc is not used)
  2766                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2767 00006CC8 <res 10h>           <1> 	p.link:	 resb nproc
  2768 00006CD8 <res 10h>           <1> 	p.stat:	 resb nproc
  2769                              <1> 
  2770                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2771 00006CE8 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2772                              <1> 			    ; 'user' structure	
  2773                              <1> 
  2774                              <1> 
  2775                              <1> P_SIZE	equ $ - process
  2776                              <1> 
  2777                              <1> 
  2778                              <1> ; fsp table (original UNIX v1)
  2779                              <1> ;
  2780                              <1> ;Entry
  2781                              <1> ;          15                                      0
  2782                              <1> ;  1     |---|---------------------------------------|
  2783                              <1> ;        |r/w|       i-number of open file           |
  2784                              <1> ;        |---|---------------------------------------| 
  2785                              <1> ;        |               device number               |
  2786                              <1> ;        |-------------------------------------------|
  2787                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2788                              <1> ;        |-------------------------------------------| 
  2789                              <1> ;        |  flag that says    | number of processes  |
  2790                              <1> ;        |   file deleted     | that have file open  |
  2791                              <1> ;        |-------------------------------------------| 
  2792                              <1> ;  2     |                                           |
  2793                              <1> ;        |-------------------------------------------| 
  2794                              <1> ;        |                                           |
  2795                              <1> ;        |-------------------------------------------|
  2796                              <1> ;        |                                           |
  2797                              <1> ;        |-------------------------------------------|
  2798                              <1> ;        |                                           |
  2799                              <1> ;        |-------------------------------------------| 
  2800                              <1> ;  3     |                                           | 
  2801                              <1> ;        |                                           |  
  2802                              <1> ;
  2803                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2804                              <1> 
  2805                              <1> 
  2806                              <1> ; 15/04/2015
  2807 00006D28 <res 1F4h>          <1> fsp:	 resb nfiles * 10 ; 11/05/2015 (8 -> 10)
  2808 00006F1C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2809 00006F3C ????                <1> ii:	 resw 1
  2810 00006F3E ????                <1> idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2811 00006F40 ????                <1> cdev:    resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2812                              <1> ; 18/05/2015
  2813                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2814                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2815                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2816                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2817                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2818                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2819                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2820                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2821                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2822                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2823                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2824 00006F42 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2825                              <1> 	        ; as above, for physical drives numbers in following table
  2826 00006F43 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2827                              <1> ; 15/04/2015
  2828 00006F44 ??                  <1> active:	 resb 1 
  2829 00006F45 ??                  <1> 	 resb 1 ; 09/06/2015
  2830 00006F46 ????                <1> mnti:	 resw 1
  2831 00006F48 ????                <1> mntp:	 resw 1 ; 14/05/2022 ; (parent dir inumber of [mnti])
  2832 00006F4A ????                <1> mpid:	 resw 1
  2833 00006F4C ????                <1> rootdir: resw 1
  2834                              <1> ; 14/02/2014
  2835                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2836                              <1> ;		      Single level run queue
  2837                              <1> ;		      (in order to solve sleep/wakeup lock)
  2838 00006F4E ????                <1> runq:	 resw 1
  2839 00006F50 ??                  <1> imod:	 resb 1
  2840 00006F51 ??                  <1> smod:	 resb 1
  2841 00006F52 ??                  <1> mmod:	 resb 1
  2842 00006F53 ??                  <1> sysflg:	 resb 1
  2843                              <1> 
  2844                              <1> alignb 4
  2845                              <1> 
  2846                              <1> user:
  2847                              <1> 	; 18/10/2015
  2848                              <1> 	; 12/10/2015
  2849                              <1> 	; 21/09/2015
  2850                              <1> 	; 24/07/2015
  2851                              <1> 	; 16/06/2015
  2852                              <1> 	; 09/06/2015
  2853                              <1> 	; 11/05/2015
  2854                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2855                              <1> 	; 10/10/2013
  2856                              <1> 	; 11/03/2013. 
  2857                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2858                              <1> 	;u.
  2859                              <1> 
  2860 00006F54 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2861 00006F58 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2862 00006F5C ????????            <1> 	u.r0:	  resd 1 ; eax
  2863 00006F60 ????                <1> 	u.cdir:	  resw 1
  2864 00006F62 <res Ah>            <1> 	u.fp:	  resb 10
  2865 00006F6C ????????            <1> 	u.fofp:	  resd 1
  2866 00006F70 ????????            <1> 	u.dirp:	  resd 1
  2867 00006F74 ????????            <1> 	u.namep:  resd 1
  2868 00006F78 ????????            <1> 	u.off:	  resd 1
  2869 00006F7C ????????            <1> 	u.base:	  resd 1
  2870 00006F80 ????????            <1> 	u.count:  resd 1
  2871 00006F84 ????????            <1> 	u.nread:  resd 1
  2872 00006F88 ????????            <1> 	u.break:  resd 1 ; break
  2873 00006F8C ????                <1> 	u.ttyp:	  resw 1 
  2874 00006F8E <res Ah>            <1> 	u.dirbuf: resb 10
  2875                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2876 00006F98 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2877 00006F99 ??                  <1> 	u.pri:	  resb 1 ; 
  2878 00006F9A ????                <1> 	u.intr:	  resw 1
  2879 00006F9C ????                <1> 	u.quit:	  resw 1
  2880                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2881 00006F9E ????                <1> 	u.ilgins: resw 1
  2882 00006FA0 ????                <1> 	u.cdrv:	  resw 1 ; cdev
  2883 00006FA2 ??                  <1> 	u.uid:	  resb 1 ; uid
  2884 00006FA3 ??                  <1> 	u.ruid:	  resb 1
  2885 00006FA4 ??                  <1> 	u.bsys:	  resb 1
  2886 00006FA5 ??                  <1> 	u.uno:	  resb 1
  2887 00006FA6 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2888                              <1> 	; tty number (rtty, rcvt, wtty)
  2889 00006FAA ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2890                              <1> 	; last error number
  2891 00006FAB ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2892                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2893 00006FAF ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2894 00006FB3 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2895 00006FB7 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2896 00006FBB ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2897                              <1> 	;u.pncount: resw 1 
  2898                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2899                              <1> 	;u.pnbase:  resd 1 
  2900                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2901                              <1> 			 ; 09/06/2015
  2902 00006FBD ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2903 00006FBE ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2904                              <1> 			 ; 24/07/2015 - 24/06/2015
  2905                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2906                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2907                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2908                              <1>  			 ; 24/06/2015	  	
  2909                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2910                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2911                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2912 00006FBF ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2913                              <1> 
  2914 00006FC3 ??                  <1> alignb 4
  2915                              <1> 
  2916                              <1> U_SIZE	equ $ - user
  2917                              <1> 
  2918                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2919 00006FC4 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2920 00006FC8 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2921 00006FCC ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2922 00006FD0 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2923 00006FD2 ????                <1> argc:	resw 1	; argument count for 'sysexec'
  2924 00006FD4 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2925                              <1> 
  2926                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2927                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2928 00006FD8 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2929 00006FD9 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2930 00006FDA ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2931 00006FDB ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2932                              <1> 
  2933                              <1> ;alignb 4
  2934                              <1> 
  2935                              <1> ; 22/08/2015
  2936 00006FDC <res C30h>          <1> buffer: resb nbuf * 520
  2937                              <1> 
  2938 00007C0C ????????????????    <1> sb0:	resd 2
  2939                              <1> ;s:
  2940                              <1> ; (root disk) super block buffer
  2941                              <1> systm:
  2942                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2943                              <1> 	; 11/03/2013. 
  2944                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  2945                              <1> 	;s.
  2946                              <1> 
  2947 00007C14 ????                <1> 	resw 1
  2948 00007C16 <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  2949 00007D7E ????                <1> 	resw 1
  2950 00007D80 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  2951                              <1> eofitab equ $ - systm ; 12/02/2022 (end of inode table)
  2952 00007DA0 ????????            <1> 	s.time:	 resd 1
  2953 00007DA4 ????????            <1> 	s.syst:	 resd 1
  2954 00007DA8 ????????            <1>         s.wait_: resd 1 ; wait
  2955 00007DAC ????????            <1> 	s.idlet: resd 1
  2956 00007DB0 ????????            <1> 	s.chrgt: resd 1
  2957 00007DB4 ????                <1> 	s.drerr: resw 1
  2958                              <1> 
  2959                              <1> S_SIZE	equ $ - systm
  2960                              <1> 
  2961 00007DB6 <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  2962                              <1> 
  2963 00007E14 ????????????????    <1> sb1:	resd 2
  2964                              <1> ; (mounted disk) super block buffer
  2965                              <1> mount:	
  2966 00007E1C <res 200h>          <1> 	resb 512  ; 03/06/2015
  2967                              <1> 
  2968                              <1> ;/ ux -- unix
  2969                              <1> ;
  2970                              <1> ;systm:
  2971                              <1> ;
  2972                              <1> ;	.=.+2
  2973                              <1> ;	.=.+128.
  2974                              <1> ;	.=.+2
  2975                              <1> ;	.=.+64.
  2976                              <1> ;	s.time: .=.+4
  2977                              <1> ;	s.syst: .=.+4
  2978                              <1> ;	s.wait: .=.+4
  2979                              <1> ;	s.idlet:.=.+4
  2980                              <1> ;	s.chrgt:.=.+4
  2981                              <1> ;	s.drerr:.=.+2
  2982                              <1> ;inode:
  2983                              <1> ;	i.flgs: .=.+2
  2984                              <1> ;	i.nlks: .=.+1
  2985                              <1> ;	i.uid:  .=.+1
  2986                              <1> ;	i.size: .=.+2
  2987                              <1> ;	i.dskp: .=.+16.
  2988                              <1> ;	i.ctim: .=.+4
  2989                              <1> ;	i.mtim: .=.+4
  2990                              <1> ;	. = inode+32.
  2991                              <1> ;mount:	.=.+1024.
  2992                              <1> ;proc:
  2993                              <1> ;	p.pid:  .=.+[2*nproc]
  2994                              <1> ;	p.dska: .=.+[2*nproc]
  2995                              <1> ;	p.ppid: .=.+[2*nproc]
  2996                              <1> ;	p.break:.=.+[2*nproc]
  2997                              <1> ;	p.link: .=.+nproc
  2998                              <1> ;	p.stat: .=.+nproc
  2999                              <1> ;tty:
  3000                              <1> ;	. = .+[ntty*8.]
  3001                              <1> ;fsp:	.=.+[nfiles*8.]
  3002                              <1> ;bufp:	.=.+[nbuf*2]+6
  3003                              <1> ;sb0:	.=.+8
  3004                              <1> ;sb1:	.=.+8
  3005                              <1> ;swp:	.=.+8
  3006                              <1> ;ii:	.=.+2
  3007                              <1> ;idev:	.=.+2
  3008                              <1> ;cdev:	.=.+2
  3009                              <1> ;deverr: .=.+12.
  3010                              <1> ;active: .=.+2
  3011                              <1> ;rfap:	.=.+2
  3012                              <1> ;rkap:	.=.+2
  3013                              <1> ;tcap:	.=.+2
  3014                              <1> ;tcstate:.=.+2
  3015                              <1> ;tcerrc: .=.+2
  3016                              <1> ;mnti:	.=.+2
  3017                              <1> ;mntd:	.=.+2
  3018                              <1> ;mpid:	.=.+2
  3019                              <1> ;clockp: .=.+2
  3020                              <1> ;rootdir:.=.+2
  3021                              <1> ;toutt:	.=.+16.
  3022                              <1> ;touts: .=.+32.
  3023                              <1> ;runq:	.=.+6
  3024                              <1> ;
  3025                              <1> ;wlist:	.=.+40.
  3026                              <1> ;cc:	.=.+30.
  3027                              <1> ;cf:	.=.+31.
  3028                              <1> ;cl:	.=.+31.
  3029                              <1> ;clist:	.=.+510.
  3030                              <1> ;imod:	.=.+1
  3031                              <1> ;smod:	.=.+1
  3032                              <1> ;mmod:	.=.+1
  3033                              <1> ;uquant: .=.+1
  3034                              <1> ;sysflg: .=.+1
  3035                              <1> ;pptiflg:.=.+1
  3036                              <1> ;ttyoch: .=.+1
  3037                              <1> ; .even
  3038                              <1> ; .=.+100.; sstack:
  3039                              <1> ;buffer: .=.+[ntty*140.]
  3040                              <1> ;	.=.+[nbuf*520.]
  3041                              <1> ;
  3042                              <1> ; . = core-64.
  3043                              <1> ;user:
  3044                              <1> ;	u.sp:    .=.+2
  3045                              <1> ;	u.usp:   .=.+2
  3046                              <1> ;	u.r0:    .=.+2
  3047                              <1> ;	u.cdir:  .=.+2
  3048                              <1> ;	u.fp:    .=.+10.
  3049                              <1> ;	u.fofp:  .=.+2
  3050                              <1> ;	u.dirp:  .=.+2
  3051                              <1> ;	u.namep: .=.+2
  3052                              <1> ;	u.off:   .=.+2
  3053                              <1> ;	u.base:  .=.+2
  3054                              <1> ;	u.count: .=.+2
  3055                              <1> ;	u.nread: .=.+2
  3056                              <1> ;	u.break: .=.+2
  3057                              <1> ;	u.ttyp:  .=.+2
  3058                              <1> ;	u.dirbuf:.=.+10.
  3059                              <1> ;	u.pri:   .=.+2
  3060                              <1> ;	u.intr:  .=.+2
  3061                              <1> ;	u.quit:  .=.+2
  3062                              <1> ;	u.emt:   .=.+2
  3063                              <1> ;	u.ilgins:.=.+2
  3064                              <1> ;	u.cdev:  .=.+2
  3065                              <1> ;	u.uid:   .=.+1
  3066                              <1> ;	u.ruid:  .=.+1
  3067                              <1> ;	u.bsys:  .=.+1
  3068                              <1> ;	u.uno:   .=.+1
  3069                              <1> ;. = core
  2719                                  
  2720                                  bss_end:
  2721                                  
  2722                                  ; 27/02/2022
  2723                                  BSS_SIZE equ bss_end - bss_start
  2724                                  
  2725                                  ; 27/12/2013
  2726                                  _end:  ; end of kernel code (and read only data, just before bss)
