     1                                  ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
     2                                  ; (re-write kernel for test by using previous version without a major defect)
     3                                  ; ****************************************************************************
     4                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.2.0
     5                                  ; ----------------------------------------------------------------------------
     6                                  ; NASM version 2.15 (unix386.s)
     7                                  ;
     8                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     9                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
    10                                  ;
    11                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    12                                  ; (v0.1 - Beginning: 11/07/2012)
    13                                  ;
    14                                  ; [ Last Modification: 31/12/2021 ]
    15                                  ;
    16                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    17                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    18                                  ; <Bell Laboratories (17/3/1972)>
    19                                  ; <Preliminary Release of UNIX Implementation Document>
    20                                  ;
    21                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    22                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    23                                  ;
    24                                  ; ****************************************************************************
    25                                  
    26                                  ; 24/12/2013
    27                                  
    28                                  ; Entering protected mode:
    29                                  ; Derived from 'simple_asm.txt' source code file and 
    30                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    31                                  ; (gregor.brunmar@home.se)
    32                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    33                                  ;
    34                                  
    35                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    36                                  ; by Michael Chourdakis (2009) 
    37                                  ; http://www.codeproject.com/Articles/45788/
    38                                  ; http://www.michaelchourdakis.com
    39                                  ;
    40                                  
    41                                  ; Global Descriptor Table:
    42                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    43                                  ; by Linus Torvalds (1991-1992)
    44                                  ;
    45                                  
    46                                  KLOAD	equ 10000h ; Kernel loading address
    47                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h 
    48                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    49                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    50                                  ; 19/03/2015
    51                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    52                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    53                                  ; 24/03/2015
    54                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    55                                  ; 19/03/2015
    56                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    57                                  		     ; (at the end of the 1st 4MB)
    58                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    59                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    60                                  
    61                                  ; 27/12/2013
    62                                  KEND    equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    63                                  
    64                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    65                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    66                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    67                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    68                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    69                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    70                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    71                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    72                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    73                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    74                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    75                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    76                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    77                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    78                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    79                                  ;----------------------------------------
    80                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    81                                  ;-----------------------------------------------------------------------------
    82                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    83                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    84                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    85                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    86                                  
    87                                  ; Memory Allocation Table Address
    88                                  ; 05/11/2014
    89                                  ; 31/10/2014
    90                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
    91                                  					; the 1st 1 MB memory space.
    92                                  					; (This address must be aligned
    93                                  					;  on 128 KB boundary, if it will be
    94                                  					;  changed later.)
    95                                  					; ((lower 17 bits of 32 bit M.A.T.
    96                                  					;   address must be ZERO)).
    97                                  					; ((((Reason: 32 bit allocation 
    98                                  					;     instructions, dword steps)))
    99                                  					; (((byte >> 12 --> page >> 5)))  
   100                                  ;04/11/2014	
   101                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   102                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   103                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   104                                  ;
   105                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   106                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   107                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   108                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   109                                  
   110                                  ; 17/02/2015 (unix386.s)
   111                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   112                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   113                                  ;
   114                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   115                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   116                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   117                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   118                                  
   119                                  
   120                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   121                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   122                                  ;
   123                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   124                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   125                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   126                                  		      ; otherwise it is standard FDPT with physical values 	
   127                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   128                                  		      ; (obsolete for IDE/ATA drives)
   129                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   130                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   131                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   132                                  			; Bit 4 : Reserved. Always 0
   133                                  			; Bit 3 : Set to 1 if more than 8 heads
   134                                  			; Bit 2-0 : Reserved. Alsways 0
   135                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   136                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   137                                  
   138                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   139                                  ; (11 bytes long) will be used by diskette handler/bios
   140                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   141                                  
   142                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   143                                  
   144                                  [ORG 0] 
   145                                  	; 12/11/2014
   146                                  	; Save boot drive number (that is default root drive)
   147 00000000 8816[2A6B]              	mov	[boot_drv], dl ; physical drv number
   148                                  
   149                                  	; Determine installed memory
   150                                  	; 31/10/2014
   151                                  	;
   152 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   153 00000007 CD15                    	int	15h	   ; for large configurations
   154 00000009 7308                    	jnc	short chk_ms
   155 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   156 0000000D CD15                    	int	15h
   157                                  	;	   
   158                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   159                                  	;out	70h, al ; select CMOS register
   160                                  	;in	al, 71h ; read data (1 byte)
   161                                  	;mov	cl, al
   162                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   163                                  	;out	70h, al ; select CMOS register
   164                                  	;in	al, 71h ; read data (1 byte)
   165                                  	;mov	ch, al
   166                                   	;      
   167 0000000F 89C1                    	mov	cx, ax
   168 00000011 31D2                    	xor	dx, dx
   169                                  chk_ms:
   170 00000013 890E[C46D]              	mov	[mem_1m_1k], cx
   171 00000017 8916[C66D]              	mov	[mem_16m_64k], dx
   172                                  	; 05/11/2014
   173                                  	;and	dx, dx
   174                                  	;jz	short L2
   175 0000001B 81F90004                        cmp     cx, 1024
   176 0000001F 7351                    	jnb	short L0
   177                                  		 ; insufficient memory_error	
   178                                  		 ; Minimum 2 MB memory is needed... 
   179                                  	; 05/11/2014
   180                                  	; (real mode error printing)
   181 00000021 FB                      	sti
   182 00000022 BE[3600]                	mov	si, msg_out_of_memory
   183 00000025 BB0700                  	mov	bx, 7
   184 00000028 B40E                    	mov	ah, 0Eh	; write tty
   185                                  oom_1:
   186 0000002A AC                      	lodsb
   187 0000002B 08C0                    	or	al, al
   188 0000002D 7404                    	jz	short oom_2
   189 0000002F CD10                    	int	10h
   190 00000031 EBF7                    	jmp	short oom_1
   191                                  oom_2:
   192 00000033 F4                              hlt
   193 00000034 EBFD                    	jmp	short oom_2
   194                                  
   195                                  ; 28/11/2021 - Retro UNIX 386 v2 compatibility modification (on v1.1)
   196                                  ; 11/04/2021 - Retro UNIX 386 v2
   197                                  ; ((Real mode messages and buffers must be in the 1st 64K of the kernel))
   198                                  ; 20/02/2017 (TRDOS 386 v2)
   199                                  ; 05/11/2014
   200                                  msg_out_of_memory:
   201 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   202 00000039 496E73756666696369-             db      'Insufficient memory !'
   202 00000042 656E74206D656D6F72-
   202 0000004B 792021             
   203 0000004E 0D0A                    	db	0Dh, 0Ah
   204                                  _int13h_48h_buffer: ; 07/07/2016
   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.s' ; 07/03/2015
   210                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   211                              <1> ; Last Modification: 04/02/2016
   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> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   218                              <1> ;L0:
   219                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   220                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   221 00000072 BA7F00              <1> 	mov	dx, 7Fh
   222                              <1> L1:	
   223 00000075 FEC2                <1> 	inc	dl
   224 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   225                              <1> 			; Phoenix EDD v1.1 - EDD v3
   226 00000079 BBAA55              <1> 	mov	bx, 55AAh
   227 0000007C CD13                <1> 	int 	13h
   228 0000007E 721A                <1> 	jc	short L2
   229                              <1> 
   230 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   231 00000084 7514                <1> 	jne	short L2
   232 00000086 FE06[2D6B]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   233 0000008A 8816[2C6B]          <1>         mov     [last_drv], dl  ; last hard disk number
   234 0000008E BB[B06A]            <1> 	mov	bx, hd0_type - 80h
   235 00000091 01D3                <1> 	add	bx, dx	 
   236 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   237                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   238                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   239                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   240                              <1>                          ;            (EDD) ready (DPTE ready)
   241                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   242                              <1>                          ;            (EDD-3)
   243                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   244 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   245 00000098 72DB                <1> 	jb	short L1
   246                              <1> L2:
   247                              <1> 	; 23/11/2014
   248                              <1> 	; 19/11/2014
   249 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   250                              <1> 	; 04/02/2016 (esi -> si)
   251 0000009C BE[2E6B]            <1> 	mov	si, fd0_type
   252                              <1> L3:
   253                              <1> 	; 14/01/2015
   254 0000009F 8816[2B6B]          <1> 	mov	[drv], dl
   255                              <1> 	;
   256 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   257 000000A5 CD13                <1> 	int	13h	
   258 000000A7 7210                <1> 	jc	short L4
   259                              <1> 		; BL = drive type (for floppy drives)
   260                              <1> 		; DL = number of floppy drives
   261                              <1> 		;		
   262                              <1> 		; ES:DI = Address of DPT from BIOS
   263                              <1> 		;
   264 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   265                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   266                              <1> 	; 14/01/2015
   267 000000AB E8A202              <1> 	call	set_disk_parms
   268                              <1> 	; 10/12/2014
   269 000000AE 81FE[2E6B]          <1> 	cmp	si, fd0_type
   270 000000B2 7705                <1> 	ja	short L4
   271 000000B4 46                  <1> 	inc	si ; fd1_type
   272 000000B5 B201                <1> 	mov	dl, 1
   273 000000B7 EBE6                <1> 	jmp	short L3
   274                              <1> L4:
   275                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   276 000000B9 B27F                <1> 	mov	dl, 7Fh
   277                              <1> 	; 24/12/2014 (Temporary)
   278 000000BB 803E[2D6B]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   279 000000C0 0F879000            <1>         ja      L10       ; yes, all fixed disk operations
   280                              <1> 			  ; will be performed according to
   281                              <1> 			  ; present EDD specification
   282                              <1> L6:
   283 000000C4 FEC2                <1> 	inc 	dl
   284 000000C6 8816[2B6B]          <1>         mov     [drv], dl
   285 000000CA 8816[2C6B]          <1>         mov     [last_drv], dl ; 14/01/2015
   286 000000CE B408                <1> 	mov 	ah, 08h ; Return drive parameters
   287 000000D0 CD13                <1> 	int	13h	; (conventional function)
   288 000000D2 0F828201            <1>         jc      L13	; fixed disk drive not ready
   289 000000D6 8816[2D6B]          <1>         mov     [hdc], dl ; number of drives
   290                              <1> 	;; 14/01/2013
   291                              <1> 	;;push	cx
   292 000000DA E87302              <1> 	call	set_disk_parms
   293                              <1> 	;;pop	cx
   294                              <1> 	;
   295                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   296 000000DD 8A16[2B6B]          <1>         mov     dl, [drv]
   297 000000E1 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   298 000000E4 80FA80              <1> 	cmp	dl, 80h
   299 000000E7 7603                <1> 	jna	short L7
   300 000000E9 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   301                              <1> L7:	
   302 000000EC 31C0                <1> 	xor	ax, ax
   303 000000EE 8ED8                <1> 	mov	ds, ax
   304 000000F0 8B37                <1>         mov     si, [bx]
   305 000000F2 8B4702              <1>         mov     ax, [bx+2] 
   306 000000F5 8ED8                <1> 	mov	ds, ax
   307 000000F7 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   308 000000FA 0F855601            <1>         jne     L12 ; invalid FDPT
   309 000000FE BF0000              <1> 	mov	di, HD0_DPT
   310 00000101 80FA80              <1> 	cmp	dl, 80h
   311 00000104 7603                <1> 	jna	short L8
   312 00000106 BF2000              <1> 	mov	di, HD1_DPT 
   313                              <1> L8:
   314                              <1> 	; 30/12/2014
   315 00000109 B80090              <1> 	mov	ax, DPT_SEGM
   316 0000010C 8EC0                <1> 	mov	es, ax
   317                              <1> 	; 24/12/2014
   318 0000010E B90800              <1> 	mov	cx, 8
   319 00000111 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   320 00000113 8CC8                <1> 	mov	ax, cs
   321 00000115 8ED8                <1> 	mov	ds, ax
   322                              <1> 	; 02/02/2015
   323 00000117 8A0E[2B6B]          <1>         mov     cl, [drv]
   324 0000011B 88CB                <1> 	mov	bl, cl
   325 0000011D B8F001              <1> 	mov	ax, 1F0h
   326 00000120 80E301              <1> 	and	bl, 1
   327 00000123 7406                <1> 	jz	short L9
   328 00000125 C0E304              <1> 	shl	bl, 4
   329 00000128 2D8000              <1> 	sub	ax, 1F0h-170h
   330                              <1> L9:
   331 0000012B AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   332 0000012C 050602              <1> 	add	ax, 206h
   333 0000012F AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   334 00000130 88D8                <1> 	mov	al, bl
   335 00000132 04A0                <1> 	add	al, 0A0h
   336 00000134 AA                  <1> 	stosb	; Device/Head Register upper nibble
   337                              <1> 	;
   338 00000135 FE06[2B6B]          <1> 	inc	byte [drv]
   339 00000139 BB[B06A]            <1> 	mov	bx, hd0_type - 80h
   340 0000013C 01CB                <1> 	add	bx, cx
   341 0000013E 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   342 00000141 A0[2D6B]            <1> 	mov	al, [hdc]
   343 00000144 FEC8                <1> 	dec	al
   344 00000146 0F840E01            <1>         jz      L13
   345 0000014A 80FA80              <1> 	cmp	dl, 80h
   346 0000014D 0F8673FF            <1>         jna     L6
   347 00000151 E90401              <1>         jmp     L13
   348                              <1> L10:
   349 00000154 FEC2                <1> 	inc 	dl
   350                              <1> 	; 25/12/2014
   351 00000156 8816[2B6B]          <1> 	mov	[drv], dl
   352 0000015A B408                <1> 	mov 	ah, 08h ; Return drive parameters
   353 0000015C CD13                <1> 	int	13h	; (conventional function)
   354 0000015E 0F82F600            <1>         jc      L13
   355                              <1> 	; 14/01/2015
   356 00000162 8A16[2B6B]          <1> 	mov	dl, [drv]
   357 00000166 52                  <1> 	push	dx
   358 00000167 51                  <1> 	push	cx
   359 00000168 E8E501              <1> 	call	set_disk_parms
   360 0000016B 59                  <1> 	pop	cx
   361 0000016C 5A                  <1> 	pop	dx
   362                              <1> 	; 04/02/2016 (esi -> si)
   363 0000016D BE[6882]            <1> 	mov	si, _end ; 30 byte temporary buffer address 	
   364                              <1> 			 ; at the '_end' of kernel.
   365 00000170 C7041E00            <1> 	mov	word [si], 30
   366 00000174 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   367 00000176 CD13                <1> 	int	13h
   368 00000178 0F82DC00            <1>         jc      L13
   369                              <1> 	; 04/02/2016 (ebx -> bx)
   370                              <1> 	; 14/01/2015
   371 0000017C 29DB                <1> 	sub	bx, bx
   372 0000017E 88D3                <1> 	mov	bl, dl
   373 00000180 80EB80              <1> 	sub	bl, 80h
   374 00000183 81C3[306B]          <1> 	add	bx, hd0_type
   375 00000187 8A07                <1> 	mov 	al, [bx]
   376 00000189 0C80                <1> 	or	al, 80h
   377 0000018B 8807                <1> 	mov 	[bx], al	
   378 0000018D 81EB[2E6B]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   379 00000191 81C3[7A6B]          <1> 	add	bx, drv.status
   380 00000195 8807                <1> 	mov	[bx], al
   381                              <1> 	; 04/02/2016 (eax -> ax)
   382 00000197 8B4410              <1> 	mov	ax, [si+16]
   383 0000019A 854412              <1> 	test	ax, [si+18]
   384 0000019D 7412                <1> 	jz	short L10_A0h 
   385                              <1> 			; 'CHS only' disks on EDD system 
   386                              <1> 			;  are reported with ZERO disk size
   387 0000019F 81EB[7A6B]          <1> 	sub	bx, drv.status
   388 000001A3 C1E302              <1> 	shl	bx, 2
   389 000001A6 81C3[5E6B]          <1> 	add	bx, drv.size ; disk size (in sectors)
   390 000001AA 8907                <1> 	mov	[bx], ax
   391 000001AC 8B4412              <1> 	mov	ax, [si+18]
   392 000001AF 8907                <1> 	mov	[bx], ax
   393                              <1> 
   394                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   395                              <1> 	 ; for CHS disks (28/02/2015)
   396                              <1> 	; 30/12/2014
   397 000001B1 BF0000              <1> 	mov	di, HD0_DPT
   398 000001B4 88D0                <1> 	mov	al, dl
   399 000001B6 83E003              <1> 	and 	ax, 3
   400 000001B9 C0E005              <1> 	shl	al, 5 ; *32
   401 000001BC 01C7                <1> 	add 	di, ax
   402 000001BE B80090              <1> 	mov	ax, DPT_SEGM
   403 000001C1 8EC0                <1> 	mov	es, ax
   404                              <1> 	;
   405 000001C3 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   406 000001C5 88CC                <1> 	mov	ah, cl	
   407 000001C7 C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   408 000001CA 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   409 000001CB AB                  <1> 	stosw		
   410 000001CC 88F0                <1> 	mov	al, dh	; max. head number
   411 000001CE FEC0                <1> 	inc	al
   412 000001D0 AA                  <1> 	stosb		; logical heads (limits 256)
   413 000001D1 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   414 000001D3 AA                  <1> 	stosb
   415 000001D4 8A440C              <1> 	mov	al, [si+12]
   416 000001D7 AA                  <1> 	stosb		 ; physical sectors per track
   417 000001D8 31C0                <1>  	xor	ax, ax
   418                              <1> 	;dec	ax	 ; 02/01/2015 
   419 000001DA AB                  <1> 	stosw		 ; precompensation (obsolete)
   420                              <1> 	;xor	al, al	 ; 02/01/2015	
   421 000001DB AA                  <1> 	stosb		 ; reserved
   422 000001DC B008                <1> 	mov	al, 8	 ; drive control byte
   423                              <1> 		         ; (do not disable retries, 
   424                              <1> 			 ; more than 8 heads)
   425 000001DE AA                  <1> 	stosb
   426 000001DF 8B4404              <1> 	mov	ax, [si+4]
   427 000001E2 AB                  <1> 	stosw		 ; physical number of cylinders	
   428                              <1> 	;push	ax	 ; 02/01/2015
   429 000001E3 8A4408              <1> 	mov	al, [si+8]
   430 000001E6 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   431 000001E7 29C0                <1> 	sub 	ax, ax
   432                              <1> 	;pop	ax	 ; 02/01/2015	
   433 000001E9 AB                  <1> 	stosw		 ; landing zone (obsolete)
   434 000001EA 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   435 000001EC 243F                <1> 	and 	al, 3Fh	
   436 000001EE AA                  <1> 	stosb
   437                              <1> 	;sub	al, al	 ; checksum
   438                              <1> 	;stosb
   439                              <1> 	;
   440 000001EF 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   441 000001F2 AD                  <1> 	lodsw
   442 000001F3 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   443 000001F4 AD                  <1> 	lodsw
   444 000001F5 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   445                              <1> 	;
   446                              <1> 	; checksum calculation
   447 000001F6 89FE                <1> 	mov	si, di
   448 000001F8 06                  <1> 	push	es
   449 000001F9 1F                  <1> 	pop	ds
   450                              <1> 	;mov	cx, 16
   451 000001FA B90F00              <1> 	mov 	cx, 15
   452 000001FD 29CE                <1> 	sub	si, cx
   453 000001FF 30E4                <1> 	xor	ah, ah
   454                              <1> 	;del	cl
   455                              <1> L11:		
   456 00000201 AC                  <1> 	lodsb
   457 00000202 00C4                <1> 	add	ah, al
   458 00000204 E2FB                <1> 	loop	L11
   459                              <1> 	;
   460 00000206 88E0                <1> 	mov	al, ah
   461 00000208 F6D8                <1> 	neg	al	; -x+x = 0
   462 0000020A AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   463                              <1> 	;
   464 0000020B 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   465 0000020C 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   466                              <1> 	;
   467                              <1> 	; 23/02/2015
   468 0000020D 57                  <1> 	push	di
   469                              <1> 	; ES:DI points to DPTE (FDPTE) location
   470                              <1> 	;mov	cx, 8
   471 0000020E B108                <1> 	mov	cl, 8
   472 00000210 F3A5                <1> 	rep	movsw	
   473                              <1> 	;
   474                              <1> 	; 23/02/2015
   475                              <1> 	; (P)ATA drive and LBA validation
   476                              <1> 	; (invalidating SATA drives and setting
   477                              <1> 	; CHS type I/O for old type fixed disks)
   478 00000212 5B                  <1> 	pop	bx
   479 00000213 8CC8                <1> 	mov	ax, cs
   480 00000215 8ED8                <1> 	mov	ds, ax
   481 00000217 268B07              <1> 	mov	ax, [es:bx]
   482 0000021A 3DF001              <1> 	cmp	ax, 1F0h
   483 0000021D 7418                <1> 	je	short L11a
   484 0000021F 3D7001              <1> 	cmp	ax, 170h
   485 00000222 7413                <1> 	je	short L11a
   486                              <1> 	; invalidation 
   487                              <1> 	; (because base port address is not 1F0h or 170h)
   488 00000224 30FF                <1> 	xor	bh, bh
   489 00000226 88D3                <1> 	mov	bl, dl
   490 00000228 80EB80              <1> 	sub	bl, 80h
   491 0000022B C687[306B]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   492 00000230 808F[7C6B]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   493 00000235 EB14                <1> 	jmp	short L11b
   494                              <1> L11a:	
   495                              <1> 	; LBA validation
   496 00000237 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   497 0000023B A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   498 0000023D 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   499                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   500 0000023F 28FF                <1> 	sub	bh, bh
   501 00000241 88D3                <1> 	mov	bl, dl
   502 00000243 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   503 00000246 80A7[7C6B]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   504                              <1> 				; bit 0 = LBA ready bit
   505                              <1> 	; 'diskio' procedure will check this bit !
   506                              <1> L11b:
   507 0000024B 3A16[2C6B]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   508 0000024F 7307                <1>         jnb     short L13
   509 00000251 E900FF              <1>         jmp     L10
   510                              <1> L12:
   511                              <1> 	; Restore data registers
   512 00000254 8CC8                <1> 	mov	ax, cs
   513 00000256 8ED8                <1> 	mov	ds, ax	
   514                              <1> L13:
   515                              <1> 	; 13/12/2014
   516 00000258 0E                  <1> 	push	cs
   517 00000259 07                  <1> 	pop	es
   518                              <1> L14:
   519 0000025A B411                <1> 	mov 	ah, 11h
   520 0000025C CD16                <1> 	int 	16h
   521 0000025E 7406                <1> 	jz 	short L15 ; no keys in keyboard buffer
   522 00000260 B010                <1> 	mov	al, 10h
   523 00000262 CD16                <1> 	int 	16h
   524 00000264 EBF4                <1> 	jmp 	short L14
   525                              <1> L15:
   526                              <1> ; //////
   527                              <1> 	; 24/11/2014
   528                              <1> 	; 19/11/2014
   529                              <1> 	; 14/11/2014
   530                              <1> 	; Temporary code for disk searching code check
   531                              <1> 	;
   532                              <1> 	; This code will show existing (usable) drives and also
   533                              <1> 	; will show EDD interface support status for hard disks		
   534                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   535                              <1> 	; no need to get it again in protected mode...) 
   536                              <1> 	;	
   537                              <1> 	; 13/11/2014
   538 00000266 BB0700              <1> 	mov	bx, 7
   539 00000269 B40E                <1> 	mov	ah, 0Eh
   540 0000026B A0[2E6B]            <1> 	mov	al, [fd0_type]
   541 0000026E 20C0                <1> 	and	al, al
   542 00000270 743D                <1> 	jz	short L15a
   543 00000272 88C2                <1> 	mov	dl, al
   544 00000274 B046                <1> 	mov	al, 'F'
   545 00000276 CD10                <1> 	int 	10h
   546 00000278 B044                <1> 	mov	al, 'D'
   547 0000027A CD10                <1> 	int 	10h
   548 0000027C B030                <1> 	mov	al, '0'
   549 0000027E CD10                <1> 	int 	10h
   550 00000280 B020                <1> 	mov	al, ' '
   551 00000282 CD10                <1> 	int	10h
   552 00000284 E8B200              <1> 	call	L15c
   553 00000287 B020                <1> 	mov	al, ' '
   554 00000289 CD10                <1> 	int	10h
   555                              <1> 	;
   556 0000028B A0[2F6B]            <1> 	mov	al, [fd1_type]
   557 0000028E 20C0                <1> 	and	al, al
   558 00000290 741D                <1> 	jz	short L15a
   559 00000292 88C2                <1> 	mov	dl, al
   560 00000294 B046                <1> 	mov	al, 'F'
   561 00000296 CD10                <1> 	int 	10h
   562 00000298 B044                <1> 	mov	al, 'D'
   563 0000029A CD10                <1> 	int 	10h
   564 0000029C B031                <1> 	mov	al, '1'
   565 0000029E CD10                <1> 	int 	10h
   566 000002A0 B020                <1> 	mov	al, ' '
   567 000002A2 CD10                <1> 	int	10h
   568 000002A4 E89200              <1> 	call	L15c
   569 000002A7 B020                <1> 	mov	al, ' '
   570 000002A9 CD10                <1> 	int	10h
   571 000002AB B020                <1> 	mov	al, ' '
   572 000002AD CD10                <1> 	int	10h
   573                              <1> L15a:
   574 000002AF A0[306B]            <1> 	mov	al, [hd0_type]
   575 000002B2 20C0                <1> 	and	al, al
   576 000002B4 7479                <1> 	jz	short L15b
   577 000002B6 88C2                <1> 	mov	dl, al
   578 000002B8 B048                <1> 	mov	al, 'H'
   579 000002BA CD10                <1> 	int 	10h
   580 000002BC B044                <1> 	mov	al, 'D'
   581 000002BE CD10                <1> 	int 	10h
   582 000002C0 B030                <1> 	mov	al, '0'
   583 000002C2 CD10                <1> 	int 	10h
   584 000002C4 B020                <1> 	mov	al, ' '
   585 000002C6 CD10                <1> 	int 	10h
   586 000002C8 E86E00              <1> 	call	L15c
   587 000002CB B020                <1> 	mov	al, ' '
   588 000002CD CD10                <1> 	int	10h
   589                              <1> 	;
   590 000002CF A0[316B]            <1> 	mov	al, [hd1_type]
   591 000002D2 20C0                <1> 	and	al, al
   592 000002D4 7459                <1> 	jz	short L15b
   593 000002D6 88C2                <1> 	mov	dl, al
   594 000002D8 B048                <1> 	mov	al, 'H'
   595 000002DA CD10                <1> 	int 	10h
   596 000002DC B044                <1> 	mov	al, 'D'
   597 000002DE CD10                <1> 	int 	10h
   598 000002E0 B031                <1> 	mov	al, '1'
   599 000002E2 CD10                <1> 	int 	10h
   600 000002E4 B020                <1> 	mov	al, ' '
   601 000002E6 CD10                <1> 	int 	10h
   602 000002E8 E84E00              <1> 	call	L15c
   603 000002EB B020                <1> 	mov	al, ' '
   604 000002ED CD10                <1> 	int	10h
   605                              <1> 	;
   606 000002EF A0[326B]            <1> 	mov	al, [hd2_type]
   607 000002F2 20C0                <1> 	and	al, al
   608 000002F4 7439                <1> 	jz	short L15b
   609 000002F6 88C2                <1> 	mov	dl, al
   610 000002F8 B048                <1> 	mov	al, 'H'
   611 000002FA CD10                <1> 	int 	10h
   612 000002FC B044                <1> 	mov	al, 'D'
   613 000002FE CD10                <1> 	int 	10h
   614 00000300 B032                <1> 	mov	al, '2'
   615 00000302 CD10                <1> 	int 	10h
   616 00000304 B020                <1> 	mov	al, ' '
   617 00000306 CD10                <1> 	int 	10h
   618 00000308 E82E00              <1> 	call	L15c
   619 0000030B B020                <1> 	mov	al, ' '
   620 0000030D CD10                <1> 	int	10h
   621                              <1> 	;
   622 0000030F A0[336B]            <1> 	mov	al, [hd3_type]
   623 00000312 20C0                <1> 	and	al, al
   624 00000314 7419                <1> 	jz	short L15b
   625 00000316 88C2                <1> 	mov	dl, al
   626 00000318 B048                <1> 	mov	al, 'H'
   627 0000031A CD10                <1> 	int 	10h
   628 0000031C B044                <1> 	mov	al, 'D'
   629 0000031E CD10                <1> 	int 	10h
   630 00000320 B033                <1> 	mov	al, '3'
   631 00000322 CD10                <1> 	int 	10h
   632 00000324 B020                <1> 	mov	al, ' '
   633 00000326 CD10                <1> 	int 	10h
   634 00000328 E80E00              <1> 	call	L15c
   635 0000032B B020                <1> 	mov	al, ' '
   636 0000032D CD10                <1> 	int	10h
   637                              <1> 	;
   638                              <1> L15b:
   639 0000032F B00D                <1> 	mov	al, 0Dh
   640 00000331 CD10                <1> 	int 	10h	
   641 00000333 B00A                <1> 	mov	al, 0Ah
   642 00000335 CD10                <1> 	int 	10h
   643                              <1> 	;;xor	ah, ah
   644                              <1> 	;;int 	16h	
   645                              <1> 	;
   646 00000337 EB77                <1>         jmp     L16  ; jmp short L16
   647                              <1>         ;
   648                              <1> L15c:
   649 00000339 88D6                <1> 	mov	dh, dl
   650 0000033B C0EE04              <1> 	shr	dh, 4
   651 0000033E 80C630              <1> 	add	dh, 30h
   652 00000341 80E20F              <1> 	and	dl, 15
   653 00000344 80C230              <1> 	add	dl, 30h
   654 00000347 88F0                <1> 	mov	al, dh
   655 00000349 CD10                <1> 	int	10h
   656 0000034B 88D0                <1> 	mov	al, dl
   657 0000034D CD10                <1> 	int	10h
   658 0000034F C3                  <1> 	retn
   659                              <1> 	;
   660                              <1> 	; end of temporary code for disk searching code check
   661                              <1> 
   662                              <1> ; //////
   663                              <1> 
   664                              <1> set_disk_parms:
   665                              <1> 	; 04/02/2016 (ebx -> bx)
   666                              <1> 	; 10/07/2015
   667                              <1> 	; 14/01/2015
   668                              <1> 	;push	bx
   669 00000350 28FF                <1> 	sub	bh, bh
   670 00000352 8A1E[2B6B]          <1> 	mov	bl, [drv]
   671 00000356 80FB80              <1> 	cmp	bl, 80h
   672 00000359 7203                <1> 	jb	short sdp0
   673 0000035B 80EB7E              <1> 	sub	bl, 7Eh
   674                              <1> sdp0:	
   675 0000035E 81C3[7A6B]          <1> 	add	bx, drv.status
   676 00000362 C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   677                              <1> 	;
   678 00000365 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   679 00000367 88CC                <1> 	mov	ah, cl ; 
   680 00000369 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   681 0000036C 81EB[7A6B]          <1> 	sub	bx, drv.status
   682 00000370 D0E3                <1> 	shl	bl, 1
   683 00000372 81C3[346B]          <1> 	add	bx, drv.cylinders
   684 00000376 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   685 00000377 8907                <1> 	mov	[bx], ax
   686 00000379 50                  <1> 	push	ax ; ** cylinders
   687 0000037A 81EB[346B]          <1> 	sub	bx, drv.cylinders
   688 0000037E 81C3[426B]          <1> 	add	bx, drv.heads
   689 00000382 30E4                <1> 	xor	ah, ah
   690 00000384 88F0                <1> 	mov	al, dh ; heads
   691 00000386 40                  <1> 	inc	ax
   692 00000387 8907                <1> 	mov	[bx], ax
   693 00000389 81EB[426B]          <1>         sub     bx, drv.heads
   694 0000038D 81C3[506B]          <1>         add     bx, drv.spt
   695 00000391 30ED                <1> 	xor	ch, ch
   696 00000393 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   697 00000396 890F                <1> 	mov	[bx], cx
   698 00000398 81EB[506B]          <1>         sub     bx, drv.spt
   699 0000039C D1E3                <1> 	shl	bx, 1
   700 0000039E 81C3[5E6B]          <1> 	add	bx, drv.size ; disk size (in sectors)
   701                              <1> 	; LBA size = cylinders * heads * secpertrack
   702 000003A2 F7E1                <1> 	mul	cx 
   703 000003A4 89C2                <1> 	mov	dx, ax	; heads*spt					
   704 000003A6 58                  <1> 	pop	ax ; ** cylinders
   705 000003A7 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   706 000003A8 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   707 000003AA 8907                <1> 	mov	[bx], ax
   708 000003AC 895702              <1> 	mov	[bx+2], dx
   709                              <1> 	;
   710                              <1> 	;pop	bx
   711 000003AF C3                  <1> 	retn
   712                              <1> 
   713                              <1> ;align 2
   714                              <1> 
   715                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   716                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   717                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   718                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   719                              <1> 
   720                              <1> ;last_drv:
   721                              <1> ;	db  0
   722                              <1> ;drv_status:
   723                              <1> ;	db  0,0,0,0,0,0
   724                              <1> ;	db 0
   725                              <1> 
   726                              <1> 
   727                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   728                              <1> 
   729                              <1> L16:
   210                                  _L0:	
   211                                  	; 10/11/2014
   212 000003B0 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 000003B1 B080                    	mov   	al, 80h 
   221 000003B3 E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   222                                  	;23/02/2015
   223 000003B5 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 000003B6 31C0                    	xor	ax, ax
   232 000003B8 8EC0                    	mov	es, ax ; ES = 0
   233                                  	;
   234 000003BA B90040                  	mov	cx, (KEND - KLOAD)/4
   235 000003BD 31F6                    	xor	si, si
   236 000003BF 31FF                    	xor	di, di
   237 000003C1 F366A5                  	rep	movsd
   238                                  	;
   239 000003C4 06                      	push	es ; 0
   240 000003C5 68[C903]                	push	L17
   241 000003C8 CB                      	retf
   242                                  	;
   243                                  L17:
   244                                  	; Turn off the floppy drive motor
   245 000003C9 BAF203                          mov     dx, 3F2h
   246 000003CC EE                              out     dx, al ; 0 ; 31/12/2013
   247                                  
   248                                  	; Enable access to memory above one megabyte
   249                                  L18:
   250 000003CD E464                    	in	al, 64h
   251 000003CF A802                    	test	al, 2
   252 000003D1 75FA                            jnz     short L18
   253 000003D3 B0D1                    	mov	al, 0D1h	; Write output port
   254 000003D5 E664                    	out	64h, al
   255                                  L19:
   256 000003D7 E464                    	in	al, 64h
   257 000003D9 A802                    	test	al, 2
   258 000003DB 75FA                            jnz     short L19
   259 000003DD B0DF                    	mov	al, 0DFh	; Enable A20 line
   260 000003DF E660                    	out	60h, al
   261                                  ;L20:
   262                                  	;
   263                                  	; Load global descriptor table register
   264                                  
   265                                          ;mov     ax, cs
   266                                          ;mov     ds, ax
   267                                  
   268 000003E1 2E0F0116[5068]                  lgdt    [cs:gdtd]
   269                                  
   270 000003E7 0F20C0                          mov     eax, cr0
   271                                  	;or 	eax, 1
   272 000003EA 40                      	inc     ax
   273 000003EB 0F22C0                  	mov     cr0, eax
   274                                  
   275                                  	; Jump to 32 bit code
   276                                  	
   277 000003EE 66                      	db	66h 		; Prefix for 32-bit
   278 000003EF EA                      	db	0EAh 		; Opcode for far jump
   279 000003F0 [F6030000]              	dd	StartPM 	; Offset to start, 32-bit
   280                                  				; (1000h:StartPM = StartPM + 10000h)
   281 000003F4 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 000003F6 66B81000                	mov	ax, KDATA	; Save data segment identifier
   289 000003FA 8ED8                            mov	ds, ax		; Move a valid data segment into DS register
   290 000003FC 8EC0                           	mov	es, ax		; Move data segment into ES register
   291 000003FE 8EE0                           	mov	fs, ax		; Move data segment into FS register
   292 00000400 8EE8                          	mov	gs, ax		; Move data segment into GS register
   293 00000402 8ED0                            mov	ss, ax		; Move data segment into SS register
   294 00000404 BC00000900                      mov	esp, 90000h	; Move the stack pointer to 090000h
   295                                  
   296                                  clear_bss: ; Clear uninitialized data area
   297                                  	; 11/03/2015
   298 00000409 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                                  	; 12/12/2021
   302 0000040B B926050000              	mov	ecx, BSS_SIZE/4
   303 00000410 BF[D06D0000]            	mov	edi, bss_start	
   304 00000415 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 00000417 B108                    	mov	cl, 8
   319 00000419 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   320 0000041E F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   321                                  				   ; for the first 1 MB memory
   322                                  	;
   323 00000420 668B0D[C46D0000]        	mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   324                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   325 00000427 66C1E902                	shr	cx, 2		   ; convert 1 KB count to 4 KB count
   326 0000042B 890D[40700000]          	mov	[free_pages], ecx
   327 00000431 668B15[C66D0000]        	mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   328                                  				   ; between 16 MB and 4 GB.	
   329 00000438 6609D2                  	or	dx, dx
   330 0000043B 7413                    	jz	short mi_0
   331                                  	;
   332 0000043D 6689D0                  	mov	ax, dx
   333 00000440 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   334 00000443 0105[40700000]          	add	[free_pages], eax
   335 00000449 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   336 0000044E EB07                    	jmp	short mi_1
   337                                  mi_0:
   338 00000450 6689C8                  	mov	ax, cx
   339 00000453 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB		 
   340                                  mi_1:
   341 00000457 A3[3C700000]            	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 0000045C 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page 	
   346 00000461 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 00000464 66A3[50700000]          	mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages		
   350 0000046A C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   351                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   352 0000046D 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   353                                  	; Set/Calculate Kernel's Page Directory Address
   354 0000046F 81C300001000            	add	ebx, MEM_ALLOC_TBL
   355 00000475 891D[38700000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   356                                  				   ; just after the last M.A.T. page
   357                                  	;
   358 0000047B 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   359 0000047E A3[48700000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   360                                  	;			   ; (allocation status search must be 
   361                                  				   ; stopped after here)	
   362 00000483 31C0                    	xor	eax, eax
   363 00000485 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)	
   364 00000486 6651                    	push	cx
   365 00000488 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to 
   366                                  				   ; count of 32 allocation bits
   367 0000048B F3AB                    	rep	stosd
   368 0000048D 6659                    	pop	cx
   369 0000048F 40                      	inc	eax		   ; 0	
   370 00000490 80E11F                  	and	cl, 31		   ; remain bits
   371 00000493 7412                    	jz	short mi_4
   372 00000495 8907                    	mov	[edi], eax	   ; reset	
   373                                  mi_2:
   374 00000497 0FAB07                  	bts	[edi], eax	   ; 06/11/2014		
   375 0000049A FEC9                    	dec	cl
   376 0000049C 7404                    	jz	short mi_3
   377 0000049E FEC0                    	inc	al
   378 000004A0 EBF5                    	jmp	short mi_2
   379                                  mi_3:
   380 000004A2 28C0                    	sub	al, al	   	   ; 0
   381 000004A4 83C704                  	add	edi, 4		   ; 15/11/2014
   382                                  mi_4:
   383 000004A7 6609D2                  	or	dx, dx		  ; check 16M to 4G memory space	
   384 000004AA 7421                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   385                                  	;	
   386 000004AC B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   387                                  	;	
   388 000004B1 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   389 000004B3 7406                    	jz	short mi_5	  ; jump if EDI points to 
   390                                  				  ;         end of first 16 MB	
   391 000004B5 D1E9                    	shr	ecx, 1		  ; convert to dword count
   392 000004B7 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   393 000004B9 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   394                                  				  ; (memory hole under 16 MB)
   395                                  mi_5:
   396 000004BB 6689D1                  	mov	cx, dx		  ; count of 64 KB memory blocks
   397 000004BE D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   398 000004C0 9C                      	pushf			  ; 16/11/2014		
   399 000004C1 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   400 000004C2 F3AB                    	rep	stosd
   401 000004C4 40                      	inc	eax		  ; 0
   402 000004C5 9D                      	popf			  ; 16/11/2014
   403 000004C6 7305                    	jnc	short mi_6
   404 000004C8 6648                    	dec	ax		  ; eax = 0000FFFFh
   405 000004CA AB                      	stosd
   406 000004CB 6640                    	inc	ax		  ; 0		
   407                                  mi_6:
   408 000004CD 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   409 000004CF 730A                    	jnb	short mi_7	  ; end of memory allocation table
   410                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   411 000004D1 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   412 000004D3 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   413 000004D5 D1E9                    	shr	ecx, 1		  ; to dword count 	 		
   414 000004D7 D1E9                    	shr	ecx, 1		  ; (shift 2 bits right) 
   415 000004D9 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 000004DB 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 000004E0 668B0D[50700000]        	mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   422 000004E7 89D7                    	mov	edi, edx
   423 000004E9 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 000004EC 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   431                                  	; eax = 0
   432 000004EE 290D[40700000]          	sub	[free_pages], ecx ; 07/11/2014
   433                                  mi_8:
   434 000004F4 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   435                                  	;dec	bl
   436 000004F7 FEC9                    	dec	cl
   437 000004F9 7404                    	jz	short mi_9
   438 000004FB FEC0                    	inc	al
   439 000004FD 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 000004FF 8B0D[3C700000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   447 00000505 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)	 	
   448 0000050B C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   449                                  				 ; page table count (PDE count)
   450                                  	;
   451 0000050E 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   452                                  	;
   453 0000050F 41                      	inc	ecx		 ; +1 for kernel page directory	
   454                                  	;
   455 00000510 290D[40700000]          	sub	[free_pages], ecx ; 07/11/2014
   456                                  	;
   457 00000516 8B35[38700000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   458 0000051C C1EE0C                  	shr	esi, 12		 ; convert to page number
   459                                  mi_10:
   460 0000051F 89F0                    	mov	eax, esi	 ; allocation bit offset		 
   461 00000521 89C3                    	mov	ebx, eax
   462 00000523 C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   463 00000526 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   464                                  				 ;   to align on dword boundary
   465 00000529 83E01F                  	and	eax, 31		 ; set allocation bit position 
   466                                  				 ;  (bit 0 to bit 31)
   467                                  	;
   468 0000052C 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   469                                  	;
   470 0000052E 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   471                                  	;
   472 00000531 46                      	inc	esi		 ; next page table
   473 00000532 E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   474                                  				 ; (ecx = page table count + 1)		
   475                                  	;
   476 00000534 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 00000535 8B3D[38700000]          	mov	edi, [k_page_dir]
   482 0000053B 89F8                    	mov	eax, edi
   483 0000053D 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   484                                  		     	      ; supervisor + read&write + present
   485 0000053F 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)	
   486                                  mi_11:
   487 00000541 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   488                                  			        ; EAX points to next page table
   489 00000546 AB                      	stosd
   490 00000547 E2F8                    	loop	mi_11
   491 00000549 29C0                    	sub	eax, eax	; Empty PDE
   492 0000054B 66B90004                	mov	cx, 1024	; Entry count (PGSZ/4)
   493 0000054F 29D1                    	sub	ecx, edx
   494 00000551 7402                    	jz	short mi_12
   495 00000553 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 00000555 8B0D[3C700000]          	mov	ecx, [memory_size] ; memory size in pages
   504 0000055B 89CA                    	mov	edx, ecx	; (***)
   505 0000055D B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   506                                  			     ; supervisor + read&write + present 	
   507                                  mi_13:
   508 0000055F AB                      	stosd
   509 00000560 0500100000              	add	eax, 4096	
   510 00000565 E2F8                    	loop	mi_13	
   511 00000567 6681E2FF03              	and	dx, 1023	; (***)
   512 0000056C 740B                    	jz	short mi_14
   513 0000056E 66B90004                	mov	cx, 1024	
   514 00000572 6629D1                  	sub	cx, dx		; from dx (<= 1023) to 1024
   515 00000575 31C0                    	xor	eax, eax
   516 00000577 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 00000579 89F8                    	mov	eax, edi	; end of the last page table page
   522                                  			        ; (beginging of user space pages)
   523 0000057B C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   524 0000057E 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   525                                  				; aligning on dword boundary	
   526                                  	 
   527 00000580 A3[4C700000]            	mov	[first_page], eax
   528 00000585 A3[44700000]            	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 0000058A A1[38700000]                    mov     eax, [k_page_dir]
   538 0000058F 0F22D8                  	mov	cr3, eax
   539 00000592 0F20C0                  	mov	eax, cr0
   540 00000595 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   541 0000059A 0F22C0                  	mov	cr0, eax
   542                                          ;jmp    KCODE:StartPMP
   543                                  
   544 0000059D EA                      	db 0EAh 		; Opcode for far jump
   545 0000059E [A4050000]                      dd StartPMP		; 32 bit offset
   546 000005A2 0800                    	dw KCODE		; kernel code segment descriptor
   547                                  
   548                                  StartPMP:
   549                                  	; 06/11//2014
   550                                  	; Clear video page 0
   551                                  	;
   552                                  	; Temporary Code
   553                                  	;
   554 000005A4 B9E8030000              	mov	ecx, 80*25/2
   555 000005A9 BF00800B00              	mov	edi, 0B8000h
   556 000005AE 31C0                    	xor	eax, eax	; black background, black fore color
   557 000005B0 F3AB                    	rep	stosd
   558                                  	
   559                                  	; 19/08/2014
   560                                  	; Kernel Base Address = 0
   561                                  	; It is mapped to (physically) 0 in the page table.
   562                                  	; So, here is exactly 'StartPMP' address.
   563                                  	;
   564                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   565                                  	;;mov	esi, msgPM
   566                                  	;; 14/08/2015 (kernel version message will appear
   567                                  	;;	       when protected mode and paging is enabled)
   568 000005B2 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   569 000005B4 BE[906B0000]            	mov	esi, msgKVER
   570 000005B9 BF00800B00              	mov	edi, 0B8000h ; 27/08/2014
   571                                  	; 20/08/2014
   572 000005BE E893010000              	call	printk
   573                                  
   574                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   575                                  	; // Set IRQ offsets
   576                                  	;
   577                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   578                                  	;
   579                                  					;; ICW1
   580 000005C3 B011                    	mov	al, 11h			; Initialization sequence
   581 000005C5 E620                    	out	20h, al			; 	8259A-1
   582                                  	; jmp 	$+2
   583 000005C7 E6A0                    	out	0A0h, al		; 	8259A-2
   584                                  					;; ICW2
   585 000005C9 B020                    	mov	al, 20h			; Start of hardware ints (20h)
   586 000005CB E621                    	out	21h, al			;	for 8259A-1
   587                                  	; jmp 	$+2
   588 000005CD B028                    	mov	al, 28h			; Start of hardware ints (28h)
   589 000005CF E6A1                    	out	0A1h, al		; 	for 8259A-2
   590                                  					;
   591 000005D1 B004                    	mov	al, 04h			;; ICW3
   592 000005D3 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   593                                  	; jmp 	$+2
   594 000005D5 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   595 000005D7 E6A1                    	out	0A1h, al		;
   596                                  					;; ICW4
   597 000005D9 B001                    	mov	al, 01h	 		;
   598 000005DB E621                    	out	21h, al			; 	8086 mode, normal EOI	
   599                                  	; jmp 	$+2
   600 000005DD E6A1                    	out	0A1h, al		;	for both chips.
   601                                  
   602                                  	;mov	al, 0FFh	; mask off all interrupts for now
   603                                  	;out	21h, al
   604                                  	;; jmp 	$+2
   605                                  	;out	0A1h, al
   606                                  
   607                                  	; 02/04/2015
   608                                  	; 26/03/2015 System call (INT 30h) modification
   609                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   610                                  	;
   611                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   612                                  	;  setup_idt:
   613                                  	;
   614                                          ;; 16/02/2015
   615                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   616                                  	; 21/08/2014 (timer_int)
   617 000005DF BE[5C680000]            	mov	esi, ilist
   618 000005E4 8D3D[D06D0000]          	lea	edi, [idt]
   619                                  	; 26/03/2015
   620 000005EA B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   621                                  	; 02/04/2015
   622 000005EF BB00000800              	mov	ebx, 80000h
   623                                  rp_sidt1:
   624 000005F4 AD                      	lodsd
   625 000005F5 89C2                    	mov	edx, eax
   626 000005F7 66BA008E                	mov	dx, 8E00h
   627 000005FB 6689C3                  	mov	bx, ax
   628 000005FE 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   629                                         			        ; /* interrupt gate - dpl=0, present */
   630 00000600 AB                      	stosd	; selector & offset bits 0-15 	
   631 00000601 89D0                    	mov	eax, edx
   632 00000603 AB                      	stosd	; attributes & offset bits 16-23
   633 00000604 E2EE                    	loop	rp_sidt1
   634 00000606 B110                    	mov	cl, 16		; 16 software interrupts (INT 30h to INT 3Fh)
   635                                  rp_sidt2:
   636 00000608 AD                      	lodsd
   637 00000609 21C0                    	and	eax, eax
   638 0000060B 7413                    	jz	short rp_sidt3
   639 0000060D 89C2                    	mov	edx, eax
   640 0000060F 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   641 00000613 6689C3                  	mov	bx, ax
   642 00000616 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   643 00000618 AB                      	stosd
   644 00000619 89D0                    	mov	eax, edx
   645 0000061B AB                      	stosd
   646 0000061C E2EA                    	loop	rp_sidt2
   647 0000061E EB16                    	jmp	short sidt_OK
   648                                  rp_sidt3:
   649 00000620 B8[780A0000]            	mov	eax, ignore_int
   650 00000625 89C2                    	mov	edx, eax
   651 00000627 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   652 0000062B 6689C3                  	mov	bx, ax
   653 0000062E 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   654                                  rp_sidt4:
   655 00000630 AB                      	stosd
   656 00000631 92                      	xchg	eax, edx
   657 00000632 AB                      	stosd
   658 00000633 92                      	xchg	edx, eax
   659 00000634 E2FA                    	loop	rp_sidt4
   660                                  sidt_OK: 
   661 00000636 0F011D[56680000]        	lidt 	[idtd]
   662                                  	;
   663                                  	; TSS descriptor setup ; 24/03/2015
   664 0000063D B8[D06F0000]            	mov	eax, task_state_segment
   665 00000642 66A3[4A680000]          	mov	[gdt_tss0], ax
   666 00000648 C1C010                  	rol	eax, 16
   667 0000064B A2[4C680000]            	mov	[gdt_tss1], al
   668 00000650 8825[4F680000]          	mov	[gdt_tss2], ah
   669 00000656 66C705[36700000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   669 0000065E 00                 
   670                                  		; 
   671                                  		; IO Map Base address (When this address points
   672                                  		; to end of the TSS, CPU does not use IO port 
   673                                  		; permission bit map for RING 3 IO permissions, 
   674                                  		; access to any IO ports in ring 3 will be forbidden.)
   675                                   		;
   676                                  	;mov	[tss.esp0], esp ; TSS offset 4
   677                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   678 0000065F 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   679                                  			 ; occurs (or a system call -software INT- is requested)
   680                                  			 ; while cpu running in ring 3 (in user mode).				
   681                                  			 ; (Kernel stack pointer and segment will be loaded
   682                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   683 00000663 0F00D8                  	ltr	ax  ; Load task register
   684                                  	;
   685                                  esp0_set0:
   686                                  	; 30/07/2015
   687 00000666 8B0D[3C700000]          	mov 	ecx, [memory_size] ; memory size in pages
   688 0000066C C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   689 0000066F 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   690                                  			  ; (kernel mode virtual address)
   691 00000675 7605                    	jna	short esp0_set1
   692                                  	;
   693                                  	; If available memory > CORE (end of the 1st 4 MB)
   694                                  	; set stack pointer to CORE
   695                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   696                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   697 00000677 B900004000              	mov	ecx, CORE
   698                                  esp0_set1:
   699 0000067C 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   700                                  esp0_set_ok:
   701                                  	; 30/07/2015 (**tss.esp0**) 
   702 0000067E 8925[D46F0000]          	mov	[tss.esp0], esp
   703 00000684 66C705[D86F0000]10-             mov     word [tss.ss0], KDATA
   703 0000068C 00                 
   704                                  	; 14/08/2015
   705                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   706                                  	;
   707                                  	;cli	; Disable interrupts (for CPU)
   708                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   709                                  	;
   710 0000068D 30C0                    	xor	al, al		; Enable all hardware interrupts!
   711 0000068F E621                    	out	21h, al		; (IBM PC-AT compatibility)
   712 00000691 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   713 00000693 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   714                                  				; (Even if related hardware component
   715                                  				;  does not exist!)
   716                                  	; Enable NMI 
   717 00000695 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   718 00000697 E670                    	out  	70h, al
   719                                  	; 23/02/2015
   720 00000699 90                      	nop
   721 0000069A E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   722                                  				; for preventing unknown state (!?)
   723                                  	;
   724                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   725                                  	;
   726                                  	; 02/09/2014
   727 0000069C 6631DB                  	xor	bx, bx
   728 0000069F 66BA0002                	mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   729 000006A3 E8390F0000              	call	set_cpos
   730                                  	;
   731                                  	; 06/11/2014
   732                                  	; Temporary Code
   733                                  	;
   734 000006A8 E856110000              	call	memory_info
   735                                  	; 14/08/2015
   736                                  	;call	getch ; 28/02/2015
   737                                  drv_init:
   738 000006AD FB                      	sti	; Enable Interrupts 
   739                                  	; 06/02/2015
   740 000006AE 8B15[306B0000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   741 000006B4 668B1D[2E6B0000]        	mov	bx, [fd0_type] ; fd0, fd1
   742                                  	; 22/02/2015
   743 000006BB 6621DB                  	and	bx, bx
   744 000006BE 751B                    	jnz	short di1
   745                                  	;
   746 000006C0 09D2                    	or 	edx, edx
   747 000006C2 7529                    	jnz	short di2
   748                                  	;
   749                                  setup_error:
   750 000006C4 BE[796C0000]            	mov 	esi, setup_error_msg
   751                                  psem:	
   752 000006C9 AC                      	lodsb
   753 000006CA 08C0                    	or	al, al
   754                                  	;jz	short haltx ; 22/02/2015
   755 000006CC 7426                    	jz	short di3
   756 000006CE 56                      	push	esi
   757 000006CF 31DB                    	xor	ebx, ebx ; 0
   758                                  			; Video page 0 (bl=0)
   759 000006D1 B407                    	mov	ah, 07h ; Black background, 
   760                                  			; light gray forecolor
   761 000006D3 E8E70D0000              	call	write_tty
   762 000006D8 5E                      	pop	esi
   763 000006D9 EBEE                    	jmp	short psem
   764                                  
   765                                  di1:
   766                                  	; supress 'jmp short T6'
   767                                  	;  (activate fdc motor control code)
   768 000006DB 66C705[D7070000]90-     	mov	word [T5], 9090h ; nop
   768 000006E3 90                 
   769                                  	;
   770                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   771                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   772                                  	;stosw
   773                                  	;mov 	ax, cs
   774                                  	;stosw
   775                                  	;; 16/02/2015
   776                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   777                                  	;
   778 000006E4 E830200000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   779                                  	;
   780 000006E9 09D2                    	or	edx, edx
   781 000006EB 7407                            jz      short di3
   782                                  di2:
   783 000006ED E86C200000              	call   	DISK_SETUP	; Initialize Fixed Disks
   784 000006F2 72D0                            jc      short setup_error
   785                                  di3:
   786 000006F4 E8DE100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   787                                  	;
   788 000006F9 E875600000              	call	display_disks ; 07/03/2015  (Temporary)
   789                                  ;haltx:
   790                                  	; 14/08/2015
   791                                  	;call	getch ; 22/02/2015
   792 000006FE FB                      	sti	; Enable interrupts (for CPU)
   793                                  	; 14/08/2015
   794                                  	;mov 	ecx, 0FFFFFFFh
   795                                  	; 22/11/2021
   796 000006FF B9FFFF2F00              	mov 	ecx, 02FFFFFh
   797                                  md_info_msg_wait:
   798 00000704 51                      	push 	ecx
   799 00000705 B001                    	mov	al, 1
   800 00000707 8A25[66700000]          	mov 	ah, [ptty] ; active (current) video page
   801 0000070D E8AC5D0000              	call	getc_n
   802 00000712 59                      	pop	ecx
   803 00000713 7502                    	jnz	short md_info_msg_ok
   804 00000715 E2ED                    	loop	md_info_msg_wait
   805                                  md_info_msg_ok:
   806                                  	; 30/06/2015
   807 00000717 E84D2D0000              	call	sys_init
   808                                  	;
   809                                  	;jmp 	cpu_reset ; 22/02/2015
   810                                  hang:
   811                                  	; 04/12/2021
   812 0000071C 29C0                    	sub	eax, eax
   813                                  _hang:	
   814                                  	; 23/02/2015
   815                                  	;sti			; Enable interrupts
   816 0000071E F4                      	hlt
   817                                  	;
   818                                  	;nop
   819                                  	;; 03/12/2014
   820                                  	;; 28/08/2014
   821                                  	;mov	ah, 11h
   822                                  	;call	getc
   823                                  	;jz      _c8
   824                                  	;
   825                                  	; 23/02/2015
   826                                  	; 06/02/2015
   827                                  	; 07/09/2014
   828 0000071F 31DB                    	xor	ebx, ebx
   829 00000721 8A1D[66700000]          	mov	bl, [ptty]	; active_page
   830 00000727 89DE                    	mov	esi, ebx
   831 00000729 66D1E6                  	shl 	si, 1
   832 0000072C 81C6[68700000]          	add	esi, ttychr
   833 00000732 668B06                  	mov	ax, [esi]
   834                                  	;and	ax, ax
   835                                  	;;jz	short _c8
   836                                  	;jz	short hang
   837                                  	; 04/12/2021
   838 00000735 21C0                    	and	eax, eax
   839 00000737 74E5                    	jz	short _hang
   840 00000739 66C7060000              	mov	word [esi], 0
   841 0000073E 80FB03                  	cmp	bl, 3		; Video page 3
   842                                  	;jb	short _c8
   843 00000741 72D9                    	jb	short hang
   844                                  	;	
   845                                  	; 02/09/2014
   846 00000743 B40E                    	mov	ah, 0Eh		; Yellow character 
   847                                  				; on black background
   848                                  	; 30/11/2021 (32 bit reg push-pop)
   849                                  	; 07/09/2014
   850                                  nxtl:
   851 00000745 53                      	push	ebx
   852                                  	;
   853                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   854                                  				; bh = 0 (video mode)
   855                                  				; Retro UNIX 386 v1 - Video Mode 0
   856                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   857 00000746 50                      	push	eax
   858 00000747 E8730D0000              	call 	write_tty
   859 0000074C 58                      	pop	eax
   860                                  	;pop	bx
   861 0000074D 5B                      	pop	ebx
   862 0000074E 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   863                                  	;jne	short _c8
   864 00000750 75CA                    	jne	short hang
   865 00000752 B00A                    	mov	al, 0Ah		; next line
   866 00000754 EBEF                    	jmp	short nxtl
   867                                  	
   868                                  ;_c8:
   869                                  ;	; 25/08/2014
   870                                  ;	cli			; Disable interrupts
   871                                  ;	mov	al, [scounter + 1]
   872                                  ;	and	al, al
   873                                  ;	jnz	hang
   874                                  ;	call	rtc_p
   875                                  ;	jmp     hang
   876                                  
   877                                  
   878                                  	; 27/08/2014
   879                                  	; 20/08/2014
   880                                  printk:
   881                                          ;mov    edi, [scr_row]
   882                                  pkl:
   883 00000756 AC                      	lodsb
   884 00000757 08C0                    	or 	al, al
   885 00000759 7404                    	jz	short pkr
   886 0000075B 66AB                    	stosw
   887 0000075D EBF7                    	jmp	short pkl
   888                                  pkr:
   889 0000075F C3                      	retn
   890                                  
   891                                  ; 25/07/2015
   892                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   893                                  ; 17/02/2015
   894                                  ; 06/02/2015 (unix386.s)
   895                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   896                                  ;
   897                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   898                                  ;
   899                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   900                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   901                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   902                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   903                                  ;									       :
   904                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   905                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   906                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   907                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   908                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   909                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   910                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   911                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   912                                  ;-------------------------------------------------------------------------------
   913                                  ;
   914                                  
   915                                  timer_int:	; IRQ 0
   916                                  ;int_08h:	; Timer
   917                                  	; 14/10/2015
   918                                  	; Here, we are simulating system call entry (for task switch)
   919                                  	; (If multitasking is enabled, 
   920                                  	; 'clock' procedure may jump to 'sysrelease')
   921 00000760 1E                      	push	ds
   922 00000761 06                      	push	es
   923 00000762 0FA0                    	push	fs
   924 00000764 0FA8                    	push	gs
   925 00000766 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   926 00000767 66B91000                	mov     cx, KDATA
   927 0000076B 8ED9                            mov     ds, cx
   928 0000076D 8EC1                            mov     es, cx
   929 0000076F 8EE1                            mov     fs, cx
   930 00000771 8EE9                            mov     gs, cx
   931                                  	;
   932 00000773 0F20D9                  	mov	ecx, cr3
   933 00000776 890D[15080000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   934                                  	;
   935 0000077C 3B0D[38700000]          	cmp 	ecx, [k_page_dir]
   936 00000782 741F                    	je	short T3
   937                                  	;
   938                                  	; timer interrupt has been occurred while OS is in user mode
   939 00000784 A3[34710000]            	mov 	[u.r0], eax
   940 00000789 89E1                    	mov	ecx, esp
   941 0000078B 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   942 0000078E 890D[2C710000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   943 00000794 8925[30710000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   944                                  	;
   945 0000079A 8B0D[38700000]          	mov	ecx, [k_page_dir]
   946 000007A0 0F22D9                  	mov	cr3, ecx
   947                                  T3:
   948 000007A3 FB                      	sti				; INTERRUPTS BACK ON
   949 000007A4 66FF05[B4700000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
   950 000007AB 7507                    	JNZ	short T4		; GO TO TEST_DAY
   951 000007AD 66FF05[B6700000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
   952                                  T4:					; TEST_DAY
   953 000007B4 66833D[B6700000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
   954 000007BC 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
   955 000007BE 66813D[B4700000]B0-     	CMP	word [TIMER_LOW],0B0H
   955 000007C6 00                 
   956 000007C7 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
   957                                  
   958                                  ;-----	TIMER HAS GONE 24 HOURS
   959                                  	;;SUB	AX,AX
   960                                  	;MOV	[TIMER_HIGH],AX
   961                                  	;MOV	[TIMER_LOW],AX
   962 000007C9 29C0                    	sub	eax, eax
   963 000007CB A3[B4700000]            	mov	[TIMER_LH], eax
   964                                  	;	
   965 000007D0 C605[B8700000]01        	MOV	byte [TIMER_OFL],1
   966                                  
   967                                  ;-----	TEST FOR DISKETTE TIME OUT
   968                                  
   969                                  T5:
   970                                  	; 23/12/2014
   971 000007D7 EB1D                    	jmp	short T6		; will be replaced with nop, nop
   972                                  					; (9090h) if a floppy disk
   973                                  					; is detected.
   974                                  	;mov	al,[CS:MOTOR_COUNT]
   975 000007D9 A0[BB700000]            	mov	al, [MOTOR_COUNT]
   976 000007DE FEC8                    	dec	al
   977                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
   978 000007E0 A2[BB700000]            	mov	[MOTOR_COUNT], al
   979                                  	;mov	[ORG_MOTOR_COUNT], al
   980 000007E5 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
   981 000007E7 B0F0                    	mov 	al,0F0h
   982                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
   983 000007E9 2005[BA700000]          	and	[MOTOR_STATUS], al
   984                                  	;and	[ORG_MOTOR_STATUS], al
   985 000007EF B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
   986                                  					; bit 2 = enable controller
   987                                  					;	1 = normal operation
   988                                  					;	0 = reset	
   989                                  					; bit 0, 1 = drive select
   990                                  					; bit 4-7 = motor running bits 
   991 000007F1 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
   992 000007F5 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
   993                                  T6:	
   994                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
   995                                  					; TIMER TICK INTERRUPT
   996                                  	;;inc	word [wait_count] ;;27/02/2015
   997                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
   998                                  	;;;;cli
   999                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1000 000007F6 FF15[11080000]          	call	[x_timer] ; 14/05/2015
  1001                                  T7:
  1002                                  	; 14/10/2015
  1003 000007FC B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1004 000007FE FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1005 000007FF E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1006                                  	;
  1007 00000801 A1[15080000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1008 00000806 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1009                                  	;
  1010 00000809 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1011                                  	;
  1012 0000080A 0FA9                    	pop	gs
  1013 0000080C 0FA1                    	pop	fs
  1014 0000080E 07                      	pop	es
  1015 0000080F 1F                      	pop	ds
  1016 00000810 CF                      	iretd	; return from interrupt
  1017                                  
  1018                                  
  1019                                  ; ////////////////
  1020                                  
  1021                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1022                                  x_timer:
  1023 00000811 [19080000]              	dd 	u_timer			; 14/05/2015
  1024                                  	;dd	clock
  1025                                  
  1026                                  ; 14/10/2015
  1027 00000815 00000000                cr3reg: dd 0
  1028                                  
  1029                                  	; 04/12/2021 - Retro UNIX 386 v1.2
  1030                                  	; 06/02/2015
  1031                                  	; 07/09/2014
  1032                                  	; 21/08/2014
  1033                                  u_timer:
  1034                                  
  1035                                  ; 31/12/2021 - temporary !
  1036 00000819 C3                      retn
  1037                                  
  1038                                  ;timer_int:	; IRQ 0
  1039                                  	; 06/02/2015
  1040                                  	;push	eax
  1041                                  	;push	edx
  1042                                  	;push	ecx
  1043                                  	;push	ebx
  1044                                  	;push	ds
  1045                                  	;push	es
  1046                                  	;mov	eax, KDATA
  1047                                  	;mov	ds, ax
  1048                                  	;mov	es, ax
  1049 0000081A FF05[7C700000]          	inc	dword [tcount]
  1050 00000820 BB[026C0000]            	mov	ebx, tcountstr + 4
  1051                                  	;mov	ax, [tcount]
  1052                                  	; 04/12/2021
  1053 00000825 A1[7C700000]            	mov	eax, [tcount]
  1054 0000082A B90A000000              	mov	ecx, 10
  1055                                  rp_divtcnt:
  1056 0000082F 31D2                    	xor	edx, edx
  1057 00000831 F7F1                    	div	ecx
  1058 00000833 80C230                  	add	dl, 30h
  1059 00000836 8813                    	mov	[ebx], dl
  1060                                  	;or	ax, ax
  1061                                  	; 04/12/2021
  1062 00000838 09C0                    	or	eax, eax
  1063 0000083A 7403                    	jz	short print_lzero
  1064 0000083C 4B                      	dec	ebx
  1065 0000083D EBF0                    	jmp	short rp_divtcnt
  1066                                  print_lzero:
  1067 0000083F 81FB[FE6B0000]          	cmp	ebx, tcountstr
  1068 00000845 7606                    	jna	short print_tcount
  1069 00000847 4B                      	dec	ebx
  1070 00000848 C60330                   	mov	byte [ebx], 30h
  1071 0000084B EBF2                    	jmp	short print_lzero
  1072                                  print_tcount:
  1073 0000084D 56                      	push	esi
  1074 0000084E 57                      	push	edi
  1075 0000084F BE[DA6B0000]            	mov	esi, timer_msg ; Timer interrupt message
  1076                                  	; 07/09/2014
  1077                                  	;mov	bx, 1		; Video page 1
  1078                                  	; 04/12/2021
  1079 00000854 29DB                    	sub	ebx, ebx
  1080 00000856 FEC3                    	inc	bl ; ebx = 1
  1081                                  ptmsg:
  1082 00000858 AC                      	lodsb
  1083 00000859 08C0                    	or	al, al
  1084 0000085B 740D                    	jz	short ptmsg_ok
  1085 0000085D 56                      	push	esi
  1086                                  	;push	bx
  1087                                  	; 04/12/2021
  1088 0000085E 53                              push	ebx
  1089 0000085F B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1090 00000861 E8590C0000              	call 	write_tty
  1091                                  	;pop	bx
  1092                                  	; 04/12/2021
  1093 00000866 5B                      	pop	ebx
  1094 00000867 5E                      	pop	esi
  1095 00000868 EBEE                    	jmp	short ptmsg
  1096                                  	;; 27/08/2014
  1097                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1098                                  	;call	printk
  1099                                  	;
  1100                                  ptmsg_ok:
  1101                                  	; 07/09/2014
  1102                                  	;xor	dx, dx		; column 0, row 0
  1103                                  	; 04/12/2021
  1104 0000086A 31D2                    	xor	edx, edx
  1105 0000086C E8700D0000              	call	set_cpos	; set cursor position to 0,0 
  1106                                  	; 23/02/2015
  1107                                  	; 25/08/2014
  1108                                  	;mov	ebx, scounter		; (seconds counter)
  1109                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1110                                  ;	dec	byte [scounter+1]
  1111                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1112                                  ;	jns	short u_timer_retn
  1113                                  	; 26/02/2015
  1114                                  ;	call	rtc_p
  1115                                  ;	mov	ebx, scounter		; (seconds counter)
  1116                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1117                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1118                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1119                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1120                                  ;	mov	byte [ebx], 5
  1121                                  ;	inc	byte [ebx+1] ; 19
  1122                                  ;;timer_eoi:
  1123                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1124                                  ;;	out	20h, al	; 8259 PORT
  1125                                  	;
  1126                                  ;u_timer_retn:  ; 06/02/2015
  1127 00000871 5F                      	pop	edi
  1128 00000872 5E                      	pop	esi
  1129                                  	;pop	es
  1130                                  	;pop	ds
  1131                                  	;pop	ebx
  1132                                  	;pop	ecx
  1133                                  	;pop	edx
  1134                                  	;pop	eax
  1135                                  	;iret
  1136 00000873 C3                      	retn	; 06/02/2015
  1137                                  
  1138                                  	; 28/08/2014
  1139                                  irq0:
  1140 00000874 6A00                            push 	dword 0
  1141 00000876 EB48                    	jmp	short which_irq
  1142                                  irq1:
  1143 00000878 6A01                            push 	dword 1
  1144 0000087A EB44                    	jmp	short which_irq
  1145                                  irq2:
  1146 0000087C 6A02                            push 	dword 2
  1147 0000087E EB40                    	jmp	short which_irq
  1148                                  irq3:
  1149                                  	; 20/11/2015
  1150                                  	; 24/10/2015
  1151 00000880 2EFF15[CA3B0000]        	call	dword [cs:com2_irq3]
  1152 00000887 6A03                    	push 	dword 3
  1153 00000889 EB35                    	jmp	short which_irq
  1154                                  irq4:
  1155                                  	; 20/11/2015
  1156                                  	; 24/10/2015
  1157 0000088B 2EFF15[C63B0000]        	call	dword [cs:com1_irq4]
  1158 00000892 6A04                            push 	dword 4
  1159 00000894 EB2A                    	jmp	short which_irq
  1160                                  irq5:
  1161 00000896 6A05                            push 	dword 5
  1162 00000898 EB26                    	jmp	short which_irq
  1163                                  irq6:
  1164 0000089A 6A06                            push 	dword 6
  1165 0000089C EB22                    	jmp	short which_irq
  1166                                  irq7:
  1167 0000089E 6A07                            push 	dword 7
  1168 000008A0 EB1E                    	jmp	short which_irq
  1169                                  irq8:
  1170 000008A2 6A08                            push 	dword 8
  1171 000008A4 EB1A                    	jmp	short which_irq
  1172                                  irq9:
  1173 000008A6 6A09                            push 	dword 9
  1174 000008A8 EB16                    	jmp	short which_irq
  1175                                  irq10:
  1176 000008AA 6A0A                            push 	dword 10
  1177 000008AC EB12                    	jmp	short which_irq
  1178                                  irq11:
  1179 000008AE 6A0B                            push 	dword 11
  1180 000008B0 EB0E                    	jmp	short which_irq
  1181                                  irq12:
  1182 000008B2 6A0C                            push 	dword 12
  1183 000008B4 EB0A                    	jmp	short which_irq
  1184                                  irq13:
  1185 000008B6 6A0D                            push 	dword 13
  1186 000008B8 EB06                    	jmp	short which_irq
  1187                                  irq14:
  1188 000008BA 6A0E                            push 	dword 14
  1189 000008BC EB02                    	jmp	short which_irq
  1190                                  irq15:
  1191 000008BE 6A0F                            push 	dword 15
  1192                                  	;jmp	short which_irq
  1193                                  
  1194                                  	; 19/10/2015
  1195                                  	; 29/08/2014
  1196                                  	; 21/08/2014
  1197                                  which_irq:
  1198 000008C0 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1199 000008C3 53                      	push	ebx
  1200 000008C4 56                      	push	esi
  1201 000008C5 57                      	push	edi
  1202 000008C6 1E                      	push 	ds
  1203 000008C7 06                      	push 	es
  1204                                  	;
  1205 000008C8 88C3                    	mov	bl, al
  1206                                  	;
  1207 000008CA B810000000              	mov	eax, KDATA
  1208 000008CF 8ED8                    	mov	ds, ax
  1209 000008D1 8EC0                    	mov	es, ax
  1210                                  	; 19/10/2015
  1211 000008D3 FC                      	cld
  1212                                          ; 27/08/2014
  1213 000008D4 8105[886B0000]A000-             add     dword [scr_row], 0A0h
  1213 000008DC 0000               
  1214                                  	;
  1215 000008DE B417                    	mov	ah, 17h	; blue (1) background, 
  1216                                  			; light gray (7) forecolor
  1217 000008E0 8B3D[886B0000]                  mov     edi, [scr_row]
  1218 000008E6 B049                    	mov	al, 'I'
  1219 000008E8 66AB                    	stosw
  1220 000008EA B052                    	mov	al, 'R'
  1221 000008EC 66AB                    	stosw
  1222 000008EE B051                    	mov	al, 'Q'
  1223 000008F0 66AB                    	stosw
  1224 000008F2 B020                    	mov	al, ' '
  1225 000008F4 66AB                    	stosw
  1226 000008F6 88D8                    	mov	al, bl
  1227 000008F8 3C0A                    	cmp	al, 10
  1228 000008FA 7208                    	jb	short iix
  1229 000008FC B031                    	mov	al, '1'
  1230 000008FE 66AB                    	stosw
  1231 00000900 88D8                    	mov	al, bl
  1232 00000902 2C0A                    	sub	al, 10
  1233                                  iix:
  1234 00000904 0430                    	add	al, '0'
  1235 00000906 66AB                    	stosw
  1236 00000908 B020                    	mov	al, ' '
  1237 0000090A 66AB                    	stosw
  1238 0000090C B021                    	mov	al, '!'
  1239 0000090E 66AB                    	stosw
  1240 00000910 B020                    	mov	al, ' '
  1241 00000912 66AB                    	stosw
  1242                                  	; 23/02/2015
  1243 00000914 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1244                                  	;jna	iiret
  1245                                  	; 04/12/2021
  1246 00000917 7604                    	jna	short iiz
  1247                                  iiy:
  1248 00000919 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1249 0000091B E6A0                    	out	0A0h, al ; the 2nd 8259
  1250                                  iiz:
  1251 0000091D E984010000              	jmp     iiret
  1252                                  	;
  1253                                  	; 22/08/2014
  1254                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1255                                  	;out	20h, al	; 8259 PORT
  1256                                  	;
  1257                                  	;pop	es
  1258                                  	;pop	ds
  1259                                  	;pop	edi
  1260                                  	;pop	esi
  1261                                  	;pop	ebx
  1262                                  	;pop 	eax
  1263                                  	;iret
  1264                                  
  1265                                  	; 02/04/2015
  1266                                  	; 25/08/2014
  1267                                  exc0:
  1268 00000922 6A00                            push 	dword 0
  1269 00000924 E990000000                      jmp     cpu_except
  1270                                  exc1:
  1271 00000929 6A01                            push 	dword 1
  1272 0000092B E989000000                      jmp     cpu_except
  1273                                  exc2:
  1274 00000930 6A02                            push 	dword 2
  1275 00000932 E982000000                      jmp     cpu_except
  1276                                  exc3:
  1277 00000937 6A03                            push 	dword 3
  1278 00000939 EB7E                            jmp     cpu_except
  1279                                  exc4:
  1280 0000093B 6A04                            push 	dword 4
  1281 0000093D EB7A                            jmp     cpu_except
  1282                                  exc5:
  1283 0000093F 6A05                            push 	dword 5
  1284 00000941 EB76                            jmp     cpu_except
  1285                                  exc6:
  1286 00000943 6A06                            push 	dword 6
  1287 00000945 EB72                            jmp     cpu_except
  1288                                  exc7:
  1289 00000947 6A07                            push 	dword 7
  1290 00000949 EB6E                            jmp     cpu_except
  1291                                  exc8:
  1292                                  	; [esp] = Error code
  1293 0000094B 6A08                            push 	dword 8
  1294 0000094D EB5C                            jmp     cpu_except_en
  1295                                  exc9:
  1296 0000094F 6A09                            push 	dword 9
  1297 00000951 EB66                            jmp     cpu_except
  1298                                  exc10:
  1299                                  	; [esp] = Error code
  1300 00000953 6A0A                            push 	dword 10
  1301 00000955 EB54                            jmp     cpu_except_en
  1302                                  exc11:
  1303                                  	; [esp] = Error code
  1304 00000957 6A0B                            push 	dword 11
  1305 00000959 EB50                            jmp     cpu_except_en
  1306                                  exc12:
  1307                                  	; [esp] = Error code
  1308 0000095B 6A0C                            push 	dword 12
  1309 0000095D EB4C                            jmp     cpu_except_en
  1310                                  exc13:
  1311                                  	; [esp] = Error code
  1312 0000095F 6A0D                            push 	dword 13
  1313 00000961 EB48                            jmp     cpu_except_en
  1314                                  exc14:
  1315                                  	; [esp] = Error code
  1316 00000963 6A0E                            push 	dword 14
  1317 00000965 EB44                    	jmp	short cpu_except_en
  1318                                  exc15:
  1319 00000967 6A0F                            push 	dword 15
  1320 00000969 EB4E                            jmp     cpu_except
  1321                                  exc16:
  1322 0000096B 6A10                            push 	dword 16
  1323 0000096D EB4A                            jmp     cpu_except
  1324                                  exc17:
  1325                                  	; [esp] = Error code
  1326 0000096F 6A11                            push 	dword 17
  1327 00000971 EB38                    	jmp	short cpu_except_en
  1328                                  exc18:
  1329 00000973 6A12                            push 	dword 18
  1330 00000975 EB42                    	jmp	short cpu_except
  1331                                  exc19:
  1332 00000977 6A13                            push 	dword 19
  1333 00000979 EB3E                    	jmp	short cpu_except
  1334                                  exc20:
  1335 0000097B 6A14                            push 	dword 20
  1336 0000097D EB3A                    	jmp	short cpu_except
  1337                                  exc21:
  1338 0000097F 6A15                            push 	dword 21
  1339 00000981 EB36                    	jmp	short cpu_except
  1340                                  exc22:
  1341 00000983 6A16                            push 	dword 22
  1342 00000985 EB32                    	jmp	short cpu_except
  1343                                  exc23:
  1344 00000987 6A17                            push 	dword 23
  1345 00000989 EB2E                    	jmp	short cpu_except
  1346                                  exc24:
  1347 0000098B 6A18                            push 	dword 24
  1348 0000098D EB2A                    	jmp	short cpu_except
  1349                                  exc25:
  1350 0000098F 6A19                            push 	dword 25
  1351 00000991 EB26                    	jmp	short cpu_except
  1352                                  exc26:
  1353 00000993 6A1A                            push 	dword 26
  1354 00000995 EB22                    	jmp	short cpu_except
  1355                                  exc27:
  1356 00000997 6A1B                            push 	dword 27
  1357 00000999 EB1E                    	jmp	short cpu_except
  1358                                  exc28:
  1359 0000099B 6A1C                            push 	dword 28
  1360 0000099D EB1A                    	jmp	short cpu_except
  1361                                  exc29:
  1362 0000099F 6A1D                            push 	dword 29
  1363 000009A1 EB16                    	jmp	short cpu_except
  1364                                  exc30:
  1365 000009A3 6A1E                            push 	dword 30
  1366 000009A5 EB04                    	jmp	short cpu_except_en
  1367                                  exc31:
  1368 000009A7 6A1F                            push 	dword 31
  1369 000009A9 EB0E                            jmp     short cpu_except
  1370                                  
  1371                                  	; 19/10/2015
  1372                                  	; 19/09/2015
  1373                                  	; 01/09/2015
  1374                                  	; 28/08/2015
  1375                                  	; 28/08/2014
  1376                                  cpu_except_en:
  1377 000009AB 87442404                	xchg	eax, [esp+4] ; Error code
  1378 000009AF 36A3[2C760000]          	mov	[ss:error_code], eax
  1379 000009B5 58                      	pop	eax  ; Exception number
  1380 000009B6 870424                  	xchg	eax, [esp]
  1381                                  		; eax = eax before exception
  1382                                  		; [esp] -> exception number
  1383                                  		; [esp+4] -> EIP to return
  1384                                  	; 19/10/2015
  1385                                  	; 19/09/2015
  1386                                  	; 01/09/2015
  1387                                  	; 28/08/2015
  1388                                  	; 29/08/2014
  1389                                  	; 28/08/2014
  1390                                  	; 25/08/2014
  1391                                  	; 21/08/2014
  1392                                  cpu_except:	; CPU Exceptions
  1393 000009B9 FC                      	cld
  1394 000009BA 870424                  	xchg	eax, [esp] 
  1395                                  		; eax = Exception number
  1396                                  		; [esp] = eax (before exception)	
  1397 000009BD 53                      	push	ebx
  1398 000009BE 56                      	push	esi
  1399 000009BF 57                      	push	edi
  1400 000009C0 1E                      	push 	ds
  1401 000009C1 06                      	push 	es
  1402                                  	; 28/08/2015
  1403 000009C2 66BB1000                	mov	bx, KDATA
  1404 000009C6 8EDB                    	mov	ds, bx
  1405 000009C8 8EC3                    	mov	es, bx
  1406 000009CA 0F20DB                  	mov	ebx, cr3
  1407 000009CD 53                      	push	ebx ; (*) page directory
  1408                                  	; 19/10/2015
  1409 000009CE FC                      	cld
  1410                                  	; 25/03/2015
  1411 000009CF 8B1D[38700000]          	mov	ebx, [k_page_dir]
  1412 000009D5 0F22DB                  	mov	cr3, ebx
  1413                                  	; 28/08/2015
  1414 000009D8 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT	
  1415 000009DB 7512                    	jne	short cpu_except_nfp
  1416 000009DD E841280000              	call	page_fault_handler
  1417 000009E2 21C0                    	and 	eax, eax
  1418 000009E4 0F84B8000000                    jz	iiretp ; 01/09/2015
  1419 000009EA B80E000000              	mov	eax, 0Eh ; 14
  1420                                  cpu_except_nfp:
  1421                                  	; 02/04/2015
  1422 000009EF BB[1C070000]            	mov	ebx, hang
  1423 000009F4 875C241C                	xchg	ebx, [esp+28]
  1424                                  		; EIP (points to instruction which faults)
  1425                                  	  	; New EIP (hang)
  1426 000009F8 891D[30760000]          	mov	[FaultOffset], ebx
  1427 000009FE C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1428 00000A06 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1429                                  	;
  1430 00000A0E 88C4                    	mov	ah, al
  1431 00000A10 240F                    	and	al, 0Fh
  1432 00000A12 3C09                    	cmp	al, 9
  1433 00000A14 7602                    	jna	short h1ok
  1434 00000A16 0407                    	add	al, 'A'-':'
  1435                                  h1ok:
  1436 00000A18 D0EC                    	shr	ah, 1
  1437 00000A1A D0EC                    	shr	ah, 1
  1438 00000A1C D0EC                    	shr	ah, 1
  1439 00000A1E D0EC                    	shr	ah, 1
  1440 00000A20 80FC09                  	cmp	ah, 9
  1441 00000A23 7603                    	jna	short h2ok
  1442 00000A25 80C407                  	add	ah, 'A'-':'
  1443                                  h2ok:	
  1444 00000A28 86E0                    	xchg 	ah, al	
  1445 00000A2A 66053030                	add	ax, '00'
  1446 00000A2E 66A3[166C0000]          	mov	[excnstr], ax
  1447                                  	;
  1448                                  	; 29/08/2014
  1449 00000A34 A1[30760000]            	mov	eax, [FaultOffset]
  1450 00000A39 51                      	push	ecx
  1451 00000A3A 52                      	push	edx
  1452 00000A3B 89E3                    	mov	ebx, esp
  1453                                  	; 28/08/2015
  1454 00000A3D B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1455                                  			  ; to hexadecimal string
  1456                                  	;mov	ecx, 10	    ; divisor to convert	
  1457                                  			    ; binary number to decimal string
  1458                                  b2d1:
  1459 00000A42 31D2                    	xor	edx, edx
  1460 00000A44 F7F1                    	div	ecx
  1461 00000A46 6652                    	push	dx
  1462 00000A48 39C8                    	cmp	eax, ecx
  1463 00000A4A 73F6                    	jnb	short b2d1
  1464 00000A4C BF[216C0000]            	mov	edi, EIPstr ; EIP value
  1465                                  			    ; points to instruction which faults	
  1466                                  	; 28/08/2015
  1467 00000A51 89C2                    	mov	edx, eax
  1468                                  b2d2:
  1469                                  	;add	al, '0'
  1470 00000A53 8A82[BF180000]          	mov	al, [edx+hexchrs]
  1471 00000A59 AA                      	stosb		    ; write hexadecimal digit to its place	
  1472 00000A5A 39E3                    	cmp	ebx, esp
  1473 00000A5C 7606                    	jna	short b2d3
  1474 00000A5E 6658                    	pop	ax
  1475 00000A60 88C2                    	mov	dl, al
  1476 00000A62 EBEF                    	jmp	short b2d2
  1477                                  b2d3:
  1478 00000A64 B068                    	mov 	al, 'h' ; 28/08/2015
  1479 00000A66 AA                      	stosb
  1480 00000A67 B020                    	mov	al, 20h	    ; space
  1481 00000A69 AA                      	stosb
  1482 00000A6A 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1483 00000A6C AA                      	stosb
  1484                                  	;
  1485 00000A6D 5A                      	pop	edx
  1486 00000A6E 59                      	pop	ecx
  1487                                  	;
  1488 00000A6F B44F                    	mov	ah, 4Fh	; red (4) background, 
  1489                                  			; white (F) forecolor
  1490 00000A71 BE[066C0000]            	mov	esi, exc_msg ; message offset
  1491                                  	;
  1492 00000A76 EB11                    	jmp	short piemsg
  1493                                  	;
  1494                                          ;add    dword [scr_row], 0A0h
  1495                                          ;mov    edi, [scr_row]
  1496                                          ;
  1497                                  	;call 	printk
  1498                                  	;
  1499                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1500                                  	;out	20h, al	; 8259 PORT
  1501                                  	;
  1502                                  	;pop	es
  1503                                  	;pop	ds
  1504                                  	;pop	edi
  1505                                  	;pop	esi
  1506                                  	;pop 	eax
  1507                                  	;iret
  1508                                  	
  1509                                  	; 28/08/2015
  1510                                  	; 23/02/2015
  1511                                  	; 20/08/2014
  1512                                  ignore_int:
  1513 00000A78 50                      	push	eax
  1514 00000A79 53                      	push	ebx ; 23/02/2015
  1515 00000A7A 56                      	push	esi
  1516 00000A7B 57                      	push	edi
  1517 00000A7C 1E                      	push 	ds
  1518 00000A7D 06                      	push 	es
  1519                                  	; 28/08/2015
  1520 00000A7E 0F20D8                  	mov	eax, cr3
  1521 00000A81 50                      	push	eax ; (*) page directory
  1522                                  	;
  1523 00000A82 B467                    	mov	ah, 67h	; brown (6) background, 
  1524                                  			; light gray (7) forecolor
  1525 00000A84 BE[C46B0000]            	mov	esi, int_msg ; message offset
  1526                                  piemsg:
  1527                                          ; 27/08/2014
  1528 00000A89 8105[886B0000]A000-             add     dword [scr_row], 0A0h
  1528 00000A91 0000               
  1529 00000A93 8B3D[886B0000]                  mov     edi, [scr_row]
  1530                                          ;
  1531 00000A99 E8B8FCFFFF              	call 	printk
  1532                                  	;
  1533                                  	; 23/02/2015
  1534 00000A9E B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1535 00000AA0 E6A0                    	out	0A0h, al ; the 2nd 8259
  1536                                  iiretp: ; 01/09/2015
  1537                                  	; 28/08/2015
  1538 00000AA2 58                      	pop	eax ; (*) page directory
  1539 00000AA3 0F22D8                  	mov	cr3, eax
  1540                                  	;
  1541                                  iiret:
  1542                                  	; 22/08/2014
  1543 00000AA6 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1544 00000AA8 E620                    	out	20h, al	; 8259 PORT
  1545                                  	;
  1546 00000AAA 07                      	pop	es
  1547 00000AAB 1F                      	pop	ds
  1548 00000AAC 5F                      	pop	edi
  1549 00000AAD 5E                      	pop	esi
  1550 00000AAE 5B                      	pop	ebx ; 29/08/2014
  1551 00000AAF 58                      	pop 	eax
  1552 00000AB0 CF                      	iretd
  1553                                  
  1554                                  	; 26/02/2015
  1555                                  	; 07/09/2014
  1556                                  	; 25/08/2014
  1557                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1558                                  	; 22/08/2014
  1559 00000AB1 50                      	push	eax
  1560 00000AB2 53                      	push	ebx ; 29/08/2014
  1561 00000AB3 56                      	push	esi
  1562 00000AB4 57                      	push	edi
  1563 00000AB5 1E                      	push 	ds
  1564 00000AB6 06                      	push 	es
  1565                                  	;
  1566 00000AB7 B810000000              	mov	eax, KDATA
  1567 00000ABC 8ED8                    	mov	ds, ax
  1568 00000ABE 8EC0                    	mov	es, ax
  1569                                  	;
  1570                                  	; 25/08/2014
  1571 00000AC0 E884000000              	call	rtc_p
  1572                                  	;
  1573                                  	; 22/02/2015 - dsectpm.s
  1574                                  	; [ source: http://wiki.osdev.org/RTC ]
  1575                                  	; read status register C to complete procedure
  1576                                  	;(it is needed to get a next IRQ 8) 
  1577 00000AC5 B00C                    	mov	al, 0Ch ; 
  1578 00000AC7 E670                    	out	70h, al ; select register C
  1579 00000AC9 90                      	nop
  1580 00000ACA E471                    	in	al, 71h ; just throw away contents
  1581                                  	; 22/02/2015
  1582 00000ACC B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1583 00000ACE E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1584                                  	;
  1585 00000AD0 EBD4                    	jmp	short iiret	
  1586                                  
  1587                                  	; 22/08/2014
  1588                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1589                                  	; (INT 1Ah)
  1590                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1591                                  time_of_day:
  1592 00000AD2 E860010000              	call	UPD_IPR			; WAIT TILL UPDATE NOT IN PROGRESS
  1593 00000AD7 726F                            jc      short rtc_retn 
  1594 00000AD9 B000                    	mov	al, CMOS_SECONDS
  1595 00000ADB E841010000              	call	CMOS_READ
  1596 00000AE0 A2[AC700000]            	mov	[time_seconds], al 
  1597 00000AE5 B002                    	mov	al, CMOS_MINUTES
  1598 00000AE7 E835010000              	call	CMOS_READ
  1599 00000AEC A2[AD700000]            	mov	[time_minutes], al 
  1600 00000AF1 B004                    	mov	al, CMOS_HOURS
  1601 00000AF3 E829010000              	call	CMOS_READ
  1602 00000AF8 A2[AE700000]                    mov     [time_hours], al
  1603 00000AFD B006                    	mov	al, CMOS_DAY_WEEK 
  1604 00000AFF E81D010000              	call	CMOS_READ
  1605 00000B04 A2[AF700000]            	mov	[date_wday], al
  1606 00000B09 B007                     	mov	al, CMOS_DAY_MONTH
  1607 00000B0B E811010000              	call	CMOS_READ
  1608 00000B10 A2[B0700000]            	mov	[date_day], al
  1609 00000B15 B008                    	mov	al, CMOS_MONTH
  1610 00000B17 E805010000              	call	CMOS_READ
  1611 00000B1C A2[B1700000]            	mov	[date_month], al
  1612 00000B21 B009                    	mov	al, CMOS_YEAR
  1613 00000B23 E8F9000000              	call	CMOS_READ
  1614 00000B28 A2[B2700000]            	mov	[date_year], al
  1615 00000B2D B032                    	mov	al, CMOS_CENTURY
  1616 00000B2F E8ED000000              	call	CMOS_READ
  1617 00000B34 A2[B3700000]            	mov	[date_century], al
  1618                                  	;
  1619 00000B39 B000                    	mov	al, CMOS_SECONDS
  1620 00000B3B E8E1000000              	call 	CMOS_READ
  1621 00000B40 3A05[AC700000]          	cmp	al, [time_seconds]
  1622 00000B46 758A                    	jne	short time_of_day
  1623                                  
  1624                                  rtc_retn:
  1625 00000B48 C3                      	retn
  1626                                  
  1627                                  rtc_p:
  1628                                  ; 31/12/2021 - temporary !
  1629 00000B49 C3                      retn	
  1630                                  	; 27/12/2021 (Retro UNIX 386 v1.2)
  1631                                  	; 07/09/2014
  1632                                  	; 29/08/2014
  1633                                  	; 27/08/2014
  1634                                  	; 25/08/2014
  1635                                   	; Print Real Time Clock content
  1636                                  	;
  1637                                  	;
  1638 00000B4A E883FFFFFF              	call	time_of_day
  1639 00000B4F 72F7                    	jc	short rtc_retn
  1640                                  	;
  1641 00000B51 3A05[786C0000]          	cmp	al, [ptime_seconds]
  1642 00000B57 74EF                            je      short rtc_retn ; 29/08/2014
  1643                                  	;
  1644 00000B59 A2[786C0000]            	mov	[ptime_seconds], al
  1645                                  	;
  1646 00000B5E A0[B3700000]            	mov	al, [date_century]
  1647 00000B63 E8EA000000              	call	bcd_to_ascii
  1648 00000B68 66A3[456C0000]          	mov	[datestr+6], ax
  1649 00000B6E A0[B2700000]            	mov	al, [date_year]
  1650 00000B73 E8DA000000              	call	bcd_to_ascii
  1651 00000B78 66A3[476C0000]          	mov	[datestr+8], ax
  1652 00000B7E A0[B1700000]            	mov	al, [date_month]
  1653 00000B83 E8CA000000              	call	bcd_to_ascii
  1654 00000B88 66A3[426C0000]          	mov	[datestr+3], ax
  1655 00000B8E A0[B0700000]            	mov	al, [date_day]
  1656 00000B93 E8BA000000              	call	bcd_to_ascii
  1657 00000B98 66A3[3F6C0000]          	mov	[datestr], ax
  1658                                  	;
  1659 00000B9E 0FB61D[AF700000]        	movzx	ebx, byte [date_wday]
  1660 00000BA5 C0E302                  	shl 	bl, 2
  1661 00000BA8 81C3[586C0000]          	add	ebx, daytmp
  1662 00000BAE 8B03                    	mov	eax, [ebx]
  1663 00000BB0 A3[4A6C0000]            	mov	[daystr], eax
  1664                                  	;
  1665 00000BB5 A0[AE700000]            	mov	al, [time_hours]
  1666 00000BBA E893000000              	call	bcd_to_ascii
  1667 00000BBF 66A3[4E6C0000]          	mov	[timestr], ax
  1668 00000BC5 A0[AD700000]            	mov	al, [time_minutes]
  1669 00000BCA E883000000              	call	bcd_to_ascii
  1670 00000BCF 66A3[516C0000]          	mov	[timestr+3], ax
  1671 00000BD5 A0[AC700000]            	mov	al, [time_seconds]
  1672 00000BDA E873000000              	call	bcd_to_ascii
  1673 00000BDF 66A3[546C0000]          	mov	[timestr+6], ax
  1674                                  	;		
  1675 00000BE5 BE[2D6C0000]            	mov	esi, rtc_msg ; message offset
  1676                                  	; 23/02/2015
  1677 00000BEA 52                      	push	edx
  1678 00000BEB 51                      	push	ecx
  1679                                  	; 07/09/2014
  1680                                  	;mov	bx, 2		; Video page 2
  1681                                  	; 27/12/2021
  1682 00000BEC 29DB                    	sub	ebx, ebx
  1683 00000BEE B302                    	mov	bl, 2
  1684                                  prtmsg:
  1685 00000BF0 AC                      	lodsb
  1686 00000BF1 08C0                    	or	al, al
  1687 00000BF3 740D                    	jz	short prtmsg_ok
  1688 00000BF5 56                      	push	esi
  1689                                  	;push	bx
  1690 00000BF6 53                              push	ebx ; 27/12/2021
  1691 00000BF7 B43F                    	mov	ah, 3Fh	; cyan (6) background, 
  1692                                  			; white (F) forecolor
  1693 00000BF9 E8C1080000              	call 	write_tty
  1694                                  	;pop	bx
  1695 00000BFE 5B                      	pop	ebx ; 27/12/2021
  1696 00000BFF 5E                      	pop	esi
  1697 00000C00 EBEE                    	jmp	short prtmsg
  1698                                  	;
  1699                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1700                                  	;call	printk
  1701                                  prtmsg_ok:
  1702                                  	; 07/09/2014
  1703                                  	;xor	dx, dx		; column 0, row 0
  1704                                  	; 27/12/2021
  1705 00000C02 31D2                    	xor	edx, edx
  1706 00000C04 E8D8090000              	call	set_cpos	; set curspor position to 0,0 
  1707                                  	; 23/02/2015
  1708 00000C09 59                      	pop	ecx
  1709 00000C0A 5A                      	pop	edx
  1710 00000C0B C3                      	retn
  1711                                  
  1712                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1713                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1714                                  default_irq7:
  1715                                  	; 04/12/2021
  1716                                  	;push	ax
  1717 00000C0C 50                      	push	eax
  1718 00000C0D B00B                    	mov	al, 0Bh  ; In-Service register
  1719 00000C0F E620                    	out	20h, al
  1720 00000C11 EB00                            jmp short $+2
  1721 00000C13 EB00                    	jmp short $+2
  1722 00000C15 E420                    	in	al, 20h
  1723 00000C17 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1724 00000C19 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1725 00000C1B B020                            mov     al, 20h ; EOI
  1726 00000C1D E620                    	out	20h, al 
  1727                                  irq7_iret:
  1728                                  	;pop	ax
  1729                                  	; 04/12/2021
  1730 00000C1F 58                      	pop	eax
  1731 00000C20 CF                      	iretd
  1732                                  	
  1733                                  	; 04/12/2021
  1734                                  	; 22/08/2014
  1735                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1736                                  CMOS_READ:
  1737 00000C21 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1738 00000C22 D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1739 00000C24 F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1740 00000C25 D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1741 00000C27 FA                      	cli		; DISABLE INTERRUPTS
  1742 00000C28 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1743 00000C2A 90                      	nop		; I/O DELAY
  1744 00000C2B E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1745                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1746                                  	; 04/12/2021
  1747 00000C2D 50                      	push	eax
  1748                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1749                                  		     ; ----- 10/06/85 (test4.asm)
  1750 00000C2E B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1751                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1752 00000C30 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1753 00000C32 E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1754                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1755                                  	; 04/12/2021
  1756 00000C34 58                      	pop	eax
  1757 00000C35 9D                      	popf	
  1758 00000C36 C3                      	retn		; RETURN WITH FLAGS RESTORED
  1759                                  
  1760                                  	; 22/08/2014
  1761                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1762                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1763 00000C37 51                      	push	ecx
  1764 00000C38 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1765                                  		; mov cx, 800	
  1766                                  UPD_10:
  1767 00000C3D B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1768 00000C3F FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1769 00000C40 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1770 00000C45 A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1771 00000C47 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1772 00000C49 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1773 00000C4A E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1774 00000C4C 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1775                                  		; xor ax, ax
  1776 00000C4E F9                      	stc				; SET CARRY FOR ERROR
  1777                                  UPD_90:
  1778 00000C4F 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1779 00000C50 FA                      	cli				; INTERRUPTS OFF DURING SET
  1780 00000C51 C3                      	retn				; RETURN WITH CY FLAG SET
  1781                                  
  1782                                  bcd_to_ascii:
  1783                                  	; 25/08/2014
  1784                                  	; INPUT ->
  1785                                  	;	al = Packed BCD number
  1786                                  	; OUTPUT ->
  1787                                  	;	ax  = ASCII word/number
  1788                                  	;
  1789                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1790                                  	;
  1791 00000C52 D410                    	db	0D4h, 10h		; Undocumented inst. AAM
  1792                                  					; AH = AL / 10h
  1793                                  					; AL = AL MOD 10h
  1794 00000C54 660D3030                	or	ax, '00'		; Make it ASCII based
  1795                                  
  1796 00000C58 86E0                            xchg	ah, al 
  1797                                  	
  1798 00000C5A C3                      	retn	
  1799                                  	
  1800                                  
  1801                                  %include 'keyboard.s' ; 07/03/2015
  1802                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1803                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1804                              <1> ; ****************************************************************************
  1805                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1806                              <1> ; Last Modification: 05/12/2021
  1807                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1808                              <1> ;
  1809                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1810                              <1> 
  1811                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  1812                              <1> ; 30/06/2015
  1813                              <1> ; 11/03/2015
  1814                              <1> ; 28/02/2015
  1815                              <1> ; 25/02/2015
  1816                              <1> ; 20/02/2015
  1817                              <1> ; 18/02/2015
  1818                              <1> ; 03/12/2014
  1819                              <1> ; 07/09/2014
  1820                              <1> ; KEYBOARD INTERRUPT HANDLER
  1821                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1822                              <1> 
  1823                              <1> ;getch:
  1824                              <1> ;	; 18/02/2015
  1825                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1826                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1827                              <1> ;	; routine, later... (multi tasking ability)
  1828                              <1> ;	; 28/02/2015
  1829                              <1> ;	sti	; enable interrupts
  1830                              <1> ;	;
  1831                              <1> ;	;push	esi
  1832                              <1> ;	;push	ebx
  1833                              <1> ;	;xor	ebx, ebx
  1834                              <1> ;	;mov	bl, [ptty]  ; active_page
  1835                              <1> ;	;mov	esi, ebx
  1836                              <1> ;	;shl 	si, 1
  1837                              <1> ;	;add	esi, ttychr
  1838                              <1> ;getch_1:
  1839                              <1> ;	;mov	ax, [esi]
  1840                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1841                              <1> ;	and	ax, ax
  1842                              <1> ;	jz	short getch_2
  1843                              <1> ;	mov	word [ttychr], 0
  1844                              <1> ;	;mov	word [esi], 0
  1845                              <1> ;	;pop	ebx
  1846                              <1> ;	;pop	esi
  1847                              <1> ;	retn
  1848                              <1> ;getch_2:
  1849                              <1> ;	hlt	; not proper for multi tasking!
  1850                              <1> ;		; (temporary halt for now)
  1851                              <1> ;		; 'sleep' on tty 
  1852                              <1> ;		; will (must) be located here		
  1853                              <1> ;	nop
  1854                              <1> ;	jmp	short getch_1
  1855                              <1> 
  1856                              <1> keyb_int:
  1857                              <1> 	; 30/06/2015
  1858                              <1> 	; 25/02/2015
  1859                              <1> 	; 20/02/2015
  1860                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1861                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1862                              <1> 	; 30/06/2014
  1863                              <1> 	; 10/05/2013	
  1864                              <1>       	; Retro Unix 8086 v1 feature only!
  1865                              <1> 	; 03/03/2014
  1866                              <1> 	
  1867 00000C5B 1E                  <1> 	push	ds
  1868 00000C5C 53                  <1> 	push	ebx
  1869 00000C5D 50                  <1> 	push	eax
  1870                              <1> 	;
  1871 00000C5E 66B81000            <1> 	mov	ax, KDATA
  1872 00000C62 8ED8                <1> 	mov	ds, ax
  1873                              <1> 	;
  1874 00000C64 9C                  <1> 	pushfd
  1875 00000C65 0E                  <1> 	push	cs
  1876 00000C66 E812020000          <1> 	call	kb_int  ; int_09h
  1877                              <1> 	;
  1878 00000C6B B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1879                              <1> 	;call	getc
  1880 00000C6D E856000000          <1> 	call	int_16h ; 30/06/2015
  1881 00000C72 7450                <1> 	jz	short keyb_int4
  1882                              <1> 	;
  1883 00000C74 B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1884                              <1> 	;call	getc
  1885 00000C76 E84D000000          <1> 	call	int_16h ; 30/06/2015
  1886                              <1> 	;
  1887                              <1> 	; 20/02/2015
  1888 00000C7B 0FB61D[66700000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1889                              <1> 	;
  1890 00000C82 20C0                <1> 	and 	al, al
  1891 00000C84 751E                <1> 	jnz	short keyb_int1
  1892                              <1> 	;
  1893 00000C86 80FC68              <1> 	cmp	ah, 68h	; ALT + F1 key
  1894 00000C89 7219                <1> 	jb	short keyb_int1
  1895 00000C8B 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1896 00000C8E 7714                <1> 	ja	short keyb_int1
  1897                              <1> 	;
  1898 00000C90 88D8                <1> 	mov	al, bl
  1899 00000C92 0468                <1> 	add	al, 68h
  1900 00000C94 38E0                <1> 	cmp	al, ah
  1901 00000C96 7409                <1> 	je	short keyb_int0
  1902 00000C98 88E0                <1> 	mov	al, ah
  1903 00000C9A 2C68                <1> 	sub	al, 68h
  1904 00000C9C E8FB0A0000          <1> 	call	tty_sw
  1905                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1906                              <1> keyb_int0: ; 30/06/2015
  1907 00000CA1 6631C0              <1> 	xor	ax, ax
  1908                              <1> keyb_int1:
  1909 00000CA4 D0E3                <1> 	shl	bl, 1
  1910 00000CA6 81C3[68700000]      <1> 	add	ebx, ttychr
  1911                              <1> 	;
  1912 00000CAC 6609C0              <1> 	or	ax, ax
  1913 00000CAF 7406                <1> 	jz	short keyb_int2
  1914                              <1> 	;
  1915 00000CB1 66833B00            <1> 	cmp 	word [ebx], 0
  1916 00000CB5 7703                <1>         ja      short keyb_int3 
  1917                              <1> keyb_int2:
  1918 00000CB7 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1919                              <1> 			   ; and scan code of the character
  1920                              <1> 			   ; for current tty (or last tty
  1921                              <1> 			   ; just before tty switch).
  1922                              <1> keyb_int3:
  1923 00000CBA A0[66700000]        <1>         mov     al, [ptty]
  1924 00000CBF E83D450000          <1> 	call	wakeup
  1925                              <1> 	;
  1926                              <1> keyb_int4:
  1927 00000CC4 58                  <1> 	pop	eax
  1928 00000CC5 5B                  <1> 	pop	ebx
  1929 00000CC6 1F                  <1> 	pop	ds
  1930 00000CC7 CF                  <1> 	iret
  1931                              <1> 
  1932                              <1> ; 18/02/2015
  1933                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  1934                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  1935                              <1> ; scancode and ascii code of the character 
  1936                              <1> ; in the tty input (ttychr) buffer. 
  1937                              <1> ; Test procedures must call 'getch' for tty input
  1938                              <1> ; otherwise, 'getc' will not be able to return to the caller
  1939                              <1> ; due to infinite (key press) waiting loop.
  1940                              <1> ; 
  1941                              <1> ; 03/12/2014
  1942                              <1> ; 26/08/2014
  1943                              <1> ; KEYBOARD I/O
  1944                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  1945                              <1> 
  1946                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  1947                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  1948                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  1949                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  1950                              <1> 
  1951                              <1> int_16h: ; 30/06/2015
  1952                              <1> ;getc:
  1953 00000CC8 9C                  <1> 	pushfd	; 28/08/2014
  1954 00000CC9 0E                  <1> 	push 	cs
  1955 00000CCA E826000000          <1> 	call 	getc_int
  1956 00000CCF C3                  <1> 	retn
  1957                              <1> 
  1958                              <1> ; 05/12/2021
  1959                              <1> 
  1960                              <1> 	;-----	SHIFT STATUS
  1961                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  1962 00000CD0 8A25[646A0000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  1963 00000CD6 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  1964                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  1965                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  1966 00000CD9 C0E405              <1>         shl	ah, 5
  1967 00000CDC A0[646A0000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  1968 00000CE1 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  1969 00000CE3 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  1970 00000CE5 A0[666A0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  1971 00000CEA 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  1972 00000CEC 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  1973                              <1> _K3:
  1974 00000CEE A0[636A0000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  1975 00000CF3 EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  1976                              <1> 
  1977                              <1> getc_int:
  1978                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  1979                              <1> 	; 28/02/2015
  1980                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  1981                              <1> 	;	      instead of pc-at bios - 1985-)
  1982                              <1> 	; 28/08/2014 (_k1d)
  1983                              <1> 	; 30/06/2014
  1984                              <1> 	; 03/03/2014
  1985                              <1> 	; 28/02/2014
  1986                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  1987                              <1> 	; rombios source code (21/04/1986)
  1988                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  1989                              <1> 	;
  1990                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  1991                              <1> 	;
  1992                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  1993                              <1> 	; KEYBOARD I/O								      :
  1994                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  1995                              <1> 	; INPUT									      :
  1996                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  1997                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  1998                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  1999                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2000                              <1> 	;-----------------------------------------------------------------------------:
  2001                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2002                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2003                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2004                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2005                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2006                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2007                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2008                              <1> 	;-----------------------------------------------------------------------------:	
  2009                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2010                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2011                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2012                              <1> 	;-----------------------------------------------------------------------------:	
  2013                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2014                              <1> 	;	      (AL) = 05H                                                      :
  2015                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2016                              <1> 	;		       							      :
  2017                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2018                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2019                              <1> 	;                     --------------------------------------------            :
  2020                              <1> 	;			00H        30.0        10H        7.5                 :
  2021                              <1> 	;			01H        26.7        11H        6.7                 :
  2022                              <1> 	;			02H        24.0        12H        6.0                 :
  2023                              <1> 	;			03H        21.8        13H        5.5                 :
  2024                              <1> 	;			04H        20.0        14H        5.0                 :
  2025                              <1> 	;			05H        18.5        15H        4.6                 :
  2026                              <1> 	;			06H        17.1        16H        4.3                 :
  2027                              <1> 	;			07H        16.0        17H        4.0                 :
  2028                              <1> 	;			08H        15.0        18H        3.7                 :
  2029                              <1> 	;			09H        13.3        19H        3.3                 :
  2030                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2031                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2032                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2033                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2034                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2035                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2036                              <1> 	;									      :
  2037                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2038                              <1> 	;		       							      :
  2039                              <1> 	;                     REGISTER     DELAY                                      :
  2040                              <1> 	;                      VALUE       VALUE                                      :
  2041                              <1> 	;                     ------------------                                      :
  2042                              <1> 	;			00H        250 ms                                     :
  2043                              <1> 	;			01H        500 ms                                     :
  2044                              <1> 	;			02H        750 ms                                     :
  2045                              <1> 	;			03H       1000 ms                                     :
  2046                              <1> 	;-----------------------------------------------------------------------------:
  2047                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2048                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2049                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2050                              <1> 	;		           (CH) = SCAN CODE                                   :
  2051                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2052                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2053                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2054                              <1> 	;-----------------------------------------------------------------------------:		
  2055                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2056                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2057                              <1> 	;-----------------------------------------------------------------------------:
  2058                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2059                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2060                              <1> 	;-----------------------------------------------------------------------------:	
  2061                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2062                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2063                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2064                              <1> 	; OUTPUT					                              :
  2065                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2066                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2067                              <1> 	;------------------------------------------------------------------------------
  2068                              <1> 	
  2069 00000CF5 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2070 00000CF6 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2071 00000CF7 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2072                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2073 00000CF8 66BB1000            <1>         mov     bx, KDATA 
  2074 00000CFC 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2075 00000CFE 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2076 00000D00 742D                <1> 	jz	short _K1		; ASCII_READ
  2077 00000D02 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2078 00000D04 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2079 00000D06 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2080 00000D08 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2081 00000D0A FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2082 00000D0C 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2083 00000D0E 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2084 00000D11 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2085                              <1> _KIO1:	
  2086 00000D13 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2087 00000D16 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2088 00000D18 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2089 00000D1A 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2090 00000D1C FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2091 00000D1E 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2092                              <1> _KIO_EXIT:
  2093                              <1> 	;pop	ecx			; RECOVER REGISTER
  2094 00000D20 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2095 00000D21 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2096 00000D22 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2097                              <1> 
  2098                              <1> 	;-----	ASCII CHARACTER
  2099                              <1> _K1E:	
  2100 00000D23 E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2101 00000D28 E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2102 00000D2D EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2103                              <1> _K1:	
  2104 00000D2F E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2105 00000D34 E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2106 00000D39 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2107                              <1> _K1A:
  2108 00000D3B EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2109                              <1> 
  2110                              <1> 	;-----	ASCII STATUS
  2111                              <1> _K2E:	
  2112 00000D3D E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2113 00000D42 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2114 00000D44 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2115 00000D45 E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2116 00000D4A EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2117                              <1> _K2:	
  2118 00000D4C E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2119 00000D51 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2120 00000D53 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2121 00000D54 E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2122 00000D59 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2123 00000D5B 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2124 00000D5C E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2125 00000D61 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2126                              <1> _K2A:
  2127 00000D63 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2128                              <1> _K2B:
  2129                              <1> 	;pop	ecx			; RECOVER REGISTER
  2130 00000D64 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2131 00000D65 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2132 00000D66 CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2133                              <1> 
  2134                              <1> ; 05/12/2021
  2135                              <1> ;	;-----	SHIFT STATUS
  2136                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2137                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2138                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2139                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2140                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2141                              <1> ;       shl	ah, 5
  2142                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2143                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2144                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2145                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2146                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2147                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2148                              <1> ;_K3:
  2149                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2150                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2151                              <1> 
  2152                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2153                              <1> _K300:
  2154 00000D69 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2155 00000D6B 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2156 00000D6D F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2157 00000D70 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2158 00000D72 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2159 00000D75 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2160 00000D77 B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2161 00000D79 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2162                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2163                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2164 00000D7E C0E705              <1> 	shl	bh, 5
  2165 00000D81 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2166 00000D83 08F8                <1> 	or	al, bh			; AND DELAY
  2167 00000D85 E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2168 00000D8A EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2169                              <1> 
  2170                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2171                              <1> _K500:
  2172 00000D8C 56                  <1> 	push	esi			; SAVE SI (esi)
  2173 00000D8D FA                  <1> 	cli				; 
  2174 00000D8E 8B1D[746A0000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2175 00000D94 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2176 00000D96 E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2177 00000D9B 3B1D[706A0000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2178 00000DA1 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2179 00000DA3 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2180 00000DA6 891D[746A0000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2181 00000DAC 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2182 00000DAE EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2183                              <1> _K502:
  2184 00000DB0 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2185                              <1> _K504:
  2186 00000DB2 FB                  <1> 	sti				
  2187 00000DB3 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2188 00000DB4 E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2189                              <1> 
  2190                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2191                              <1> _K1S:
  2192 00000DB9 FA                  <1> 	cli	; 03/12/2014
  2193 00000DBA 8B1D[706A0000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2194 00000DC0 3B1D[746A0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2195                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2196 00000DC6 750F                <1> 	jne	short _k1x ; 03/12/2014
  2197                              <1> 	;
  2198                              <1> 	; 03/12/2014
  2199                              <1> 	; 28/08/2014
  2200                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2201                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2202                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2203                              <1> _K1T:                                   ; ASCII READ
  2204 00000DC8 FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2205 00000DC9 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2206                              <1> _K1U:	
  2207 00000DCA FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2208 00000DCB 8B1D[706A0000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2209 00000DD1 3B1D[746A0000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2210                              <1> _k1x:
  2211 00000DD7 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2212 00000DD8 9C                  <1> 	pushf				; SAVE FLAGS
  2213 00000DD9 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2214 00000DDE 8A1D[656A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2215 00000DE4 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2216 00000DE6 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2217 00000DE9 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2218 00000DEB E86E060000          <1> 	call	SND_LED1
  2219 00000DF0 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2220                              <1> _K1V:
  2221 00000DF1 9D                  <1> 	popf				; RESTORE FLAGS
  2222 00000DF2 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2223 00000DF3 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2224                              <1> 	;
  2225 00000DF5 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2226 00000DF8 E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2227 00000DFD 891D[706A0000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2228 00000E03 C3                  <1> 	retn				; RETURN
  2229                              <1> 
  2230                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2231                              <1> _K2S:
  2232 00000E04 FA                  <1> 	cli				; INTERRUPTS OFF
  2233 00000E05 8B1D[706A0000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2234 00000E0B 3B1D[746A0000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2235 00000E11 668B03              <1> 	mov	ax, [ebx]
  2236 00000E14 9C                  <1> 	pushf				; SAVE FLAGS
  2237                              <1> 	;push	ax			; SAVE CODE
  2238                              <1> 	; 05/12/2021
  2239 00000E15 50                  <1> 	push	eax
  2240 00000E16 E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2241 00000E1B 8A1D[656A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2242 00000E21 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2243 00000E23 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2244 00000E26 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2245 00000E28 E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2246                              <1> _K2T:
  2247                              <1> 	;pop	ax			; RESTORE CODE
  2248                              <1> 	; 05/12/2021
  2249 00000E2D 58                  <1> 	pop	eax
  2250 00000E2E 9D                  <1> 	popf				; RESTORE FLAGS
  2251 00000E2F FB                  <1> 	sti				; INTERRUPTS BACK ON
  2252 00000E30 C3                  <1> 	retn				; RETURN
  2253                              <1> 
  2254                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2255                              <1> _KIO_E_XLAT:
  2256 00000E31 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2257 00000E33 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2258 00000E35 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2259 00000E37 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2260 00000E39 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2261                              <1> _KIO_E_RET:				
  2262 00000E3B C3                  <1> 	retn				; GO BACK
  2263                              <1> 
  2264                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2265                              <1> _KIO_S_XLAT:
  2266 00000E3C 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2267 00000E3F 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2268 00000E41 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2269 00000E43 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2270 00000E45 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2271 00000E47 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2272 00000E49 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2273                              <1> _kio_ret: ; 03/12/2014
  2274 00000E4B F8                  <1> 	clc
  2275 00000E4C C3                  <1> 	retn
  2276                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2277                              <1> _KIO_S1:				
  2278 00000E4D B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2279                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2280 00000E4F C3                  <1> 	retn
  2281                              <1> _KIO_S2:		
  2282 00000E50 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2283 00000E53 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2284 00000E55 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2285 00000E57 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2286 00000E59 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2287 00000E5B 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2288 00000E5D EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2289                              <1> _KIO_S3:
  2290 00000E5F 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2291                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2292 00000E61 75E8                <1> 	jne	short _kio_ret
  2293 00000E63 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2294 00000E65 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2295 00000E67 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2296                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2297                              <1> _KIO_USE:
  2298                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2299 00000E69 C3                  <1> 	retn				; RETURN	
  2300                              <1> _KIO_DIS:
  2301 00000E6A F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2302 00000E6B C3                  <1> 	retn				; RETURN
  2303                              <1> 
  2304                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2305                              <1> _K4:    
  2306 00000E6C 43                  <1> 	inc     ebx
  2307 00000E6D 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2308 00000E6E 3B1D[6C6A0000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2309                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2310 00000E74 7206                <1> 	jb	short _K5
  2311 00000E76 8B1D[686A0000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2312                              <1> _K5:
  2313 00000E7C C3                  <1> 	retn
  2314                              <1> 
  2315                              <1> ; 20/02/2015
  2316                              <1> ; 05/12/2014
  2317                              <1> ; 26/08/2014
  2318                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2319                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2320                              <1> ;
  2321                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2322                              <1> ; rombios source code (06/10/1985)
  2323                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2324                              <1> 
  2325                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2326                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2327                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2328                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2329                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2330                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2331                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2332                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2333                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2334                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2335                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2336                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2337                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2338                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2339                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2340                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2341                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2342                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2343                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2344                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2345                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2346                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2347                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2348                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2349                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2350                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2351                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2352                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2353                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2354                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2355                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2356                              <1> F11_M		equ	87		; F11 KEY MAKE
  2357                              <1> F12_M		equ	88		; F12 KEY MAKE
  2358                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2359                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2360                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2361                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2362                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2363                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2364                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2365                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2366                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2367                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2368                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2369                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2370                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2371                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2372                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2373                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2374                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2375                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2376                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2377                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2378                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2379                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2380                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2381                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2382                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2383                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2384                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2385                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2386                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2387                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2388                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2389                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2390                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2391                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2392                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2393                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2394                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2395                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2396                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2397                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2398                              <1> ;
  2399                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2400                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2401                              <1> INTA00		equ	020h		; 8259 PORT
  2402                              <1> 
  2403                              <1> 
  2404                              <1> kb_int:
  2405                              <1> 
  2406                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2407                              <1> ; 17/10/2015 ('ctrlbrk') 
  2408                              <1> ; 05/12/2014
  2409                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2410                              <1> 	;	      instead of pc-at bios - 1985-)
  2411                              <1> ; 26/08/2014
  2412                              <1> ;
  2413                              <1> ; 03/06/86  KEYBOARD BIOS
  2414                              <1> ;
  2415                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2416                              <1> ;										;
  2417                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2418                              <1> ;										;
  2419                              <1> ;--------------------------------------------------------------------------------
  2420                              <1> 
  2421                              <1> KB_INT_1:
  2422 00000E7D FB                  <1> 	sti				; ENABLE INTERRUPTS
  2423                              <1> 	;push	ebp
  2424 00000E7E 50                  <1> 	push	eax
  2425 00000E7F 53                  <1> 	push	ebx
  2426 00000E80 51                  <1> 	push	ecx
  2427 00000E81 52                  <1> 	push	edx
  2428 00000E82 56                  <1> 	push	esi
  2429 00000E83 57                  <1> 	push	edi
  2430 00000E84 1E                  <1> 	push	ds
  2431 00000E85 06                  <1> 	push	es
  2432 00000E86 FC                  <1> 	cld				; FORWARD DIRECTION
  2433 00000E87 66B81000            <1> 	mov	ax, KDATA
  2434 00000E8B 8ED8                <1> 	mov	ds, ax
  2435 00000E8D 8EC0                <1> 	mov	es, ax
  2436                              <1> 	;
  2437                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2438 00000E8F B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2439 00000E91 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2440 00000E96 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2441 00000E97 B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2442                              <1> KB_INT_01:
  2443 00000E9C E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2444 00000E9E A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2445 00000EA0 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2446                              <1> 	;
  2447                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2448 00000EA2 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2449                              <1> 	;
  2450                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2451                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2452                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2453                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2454                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2455                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2456                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2457                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2458                              <1> 	;
  2459                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2460                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2461 00000EA4 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2462 00000EA5 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2463 00000EA7 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2464                              <1> 	;
  2465                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2466 00000EA9 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2467 00000EAB 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2468                              <1> 	;
  2469                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2470 00000EAD FA                  <1> 	cli				; DISABLE INTERRUPTS
  2471 00000EAE 800D[656A0000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2472 00000EB5 E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2473                              <1> 	;
  2474                              <1> 	;-----	RESEND THE LAST BYTE
  2475                              <1> KB_INT_4:
  2476 00000EBA FA                  <1> 	cli				; DISABLE INTERRUPTS
  2477 00000EBB 800D[656A0000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2478 00000EC2 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2479                              <1> 	;
  2480                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2481                              <1> KB_INT_2:
  2482                              <1> 	;push 	ax			; SAVE DATA IN
  2483                              <1> 	; 05/12/2021
  2484 00000EC7 50                  <1> 	push	eax
  2485 00000EC8 E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2486 00000ECD 8A1D[656A0000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2487 00000ED3 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2488 00000ED5 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2489 00000ED8 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2490 00000EDA E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2491                              <1> UP0:
  2492                              <1> 	;pop	ax			; RESTORE DATA IN
  2493                              <1> 	; 05/12/2021
  2494 00000EDF 58                  <1> 	pop	eax
  2495                              <1> ;------------------------------------------------------------------------
  2496                              <1> ;	START OF KEY PROCESSING						;
  2497                              <1> ;------------------------------------------------------------------------
  2498 00000EE0 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2499                              <1> 	;
  2500                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2501 00000EE2 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2502                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2503                              <1> 	; 05/12/2021
  2504 00000EE4 7505                <1> 	jne	short K16
  2505 00000EE6 E9ED040000          <1> 	jmp	K62
  2506                              <1> K16:	
  2507 00000EEB 8A3D[666A0000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2508                              <1> 	;
  2509                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2510 00000EF1 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2511 00000EF4 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2512 00000EF6 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2513 00000EF8 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2514 00000EFA 7507                <1> 	jne	short RST_RD_ID
  2515 00000EFC 800D[666A0000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2516                              <1> RST_RD_ID:
  2517 00000F03 8025[666A0000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2518 00000F0A EB27                <1>         jmp    short ID_EX		; AND EXIT
  2519                              <1> 	; 05/12/2021
  2520                              <1> 	;jmp	K26
  2521                              <1> 	;
  2522                              <1> TST_ID_2:
  2523 00000F0C 8025[666A0000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2524 00000F13 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2525 00000F15 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2526 00000F17 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2527 00000F19 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2528                              <1> 	; 05/12/2021
  2529                              <1> 	;jne	K26
  2530                              <1> 	;
  2531                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2532 00000F1B F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2533 00000F1E 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2534 00000F20 800D[636A0000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2535 00000F27 E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2536                              <1> KX_BIT:
  2537 00000F2C 800D[666A0000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2538 00000F33 E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2539                              <1> 	;
  2540                              <1> NOT_ID:
  2541 00000F38 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2542 00000F3A 750E                <1> 	jne	short TEST_E1
  2543 00000F3C 800D[666A0000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2544 00000F43 EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2545                              <1> 	; 05/12/2021
  2546 00000F45 E9DA010000          <1> 	jmp	K26A	
  2547                              <1> TEST_E1:	
  2548 00000F4A 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2549 00000F4C 750C                <1> 	jne	short NOT_HC
  2550 00000F4E 800D[666A0000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2551 00000F55 E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2552                              <1> 	;
  2553                              <1> NOT_HC:
  2554 00000F5A 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2555 00000F5C F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2556 00000F5F 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2557                              <1> 	;
  2558 00000F61 BF[4E690000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2559 00000F66 AE                  <1> 	scasb
  2560                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2561                              <1> 	; 05/12/2021
  2562 00000F67 7458                <1> 	je	short K16B
  2563 00000F69 AE                  <1> 	scasb
  2564 00000F6A 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2565 00000F6C EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2566                              <1> 	; 05/12/2021
  2567                              <1> 	;jmp	K26
  2568                              <1> 	;
  2569                              <1> NOT_LC_E0:
  2570 00000F6E F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2571 00000F71 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2572 00000F73 B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2573 00000F78 BF[4C690000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2574 00000F7D F2AE                <1> 	repne	scasb			; CHECK IT
  2575 00000F7F 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2576                              <1> 	; 05/12/2021
  2577                              <1> 	;je	K26A			
  2578                              <1> 	;
  2579 00000F81 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2580 00000F83 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2581                              <1> 	; 05/12/2021
  2582                              <1> 	;jne	K26
  2583 00000F85 F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2584 00000F88 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2585                              <1> 	; 05/12/2021
  2586                              <1> 	;jnz	K26
  2587                              <1>         ; 20/02/2015 
  2588 00000F8A F605[646A0000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2589 00000F91 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2590                              <1> 	; 05/12/2021
  2591                              <1> 	;jnz	K26
  2592 00000F93 E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2593                              <1> 	;
  2594                              <1> 	;-----	TEST FOR SYSTEM KEY
  2595                              <1> T_SYS_KEY:
  2596 00000F98 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2597 00000F9A 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2598                              <1> 	;
  2599 00000F9C F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2600 00000F9F 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2601                              <1> 	;
  2602 00000FA1 F605[646A0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2603 00000FA8 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2604                              <1> 	;jnz	K26			
  2605                              <1> 	;
  2606 00000FAA 800D[646A0000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2607 00000FB1 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2608 00000FB3 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2609                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2610 00000FB5 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2611 00000FB7 E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2612                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2613                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2614                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2615                              <1> 	;INT	15H			; USER INTERRUPT	
  2616 00000FBC E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2617                              <1> 	;
  2618 00000FC1 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2619                              <1> 	;
  2620                              <1> K16C:
  2621 00000FC6 8025[646A0000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2622 00000FCD B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2623 00000FCF E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2624                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2625                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2626                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2627                              <1> 	;
  2628                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2629                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2630                              <1> 	;INT	15H			; USER INTERRUPT
  2631                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2632                              <1> 	;
  2633 00000FD1 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2634                              <1> 	;
  2635                              <1> 	;-----	TEST FOR SHIFT KEYS
  2636                              <1> K16A:
  2637 00000FD6 8A1D[636A0000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2638 00000FDC BF[48690000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2639 00000FE1 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2640 00000FE6 F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2641 00000FE8 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2642                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2643                              <1> 	; 05/12/2021
  2644 00000FEA 7405                <1> 	je	short K17
  2645 00000FEC E914010000          <1> 	jmp	K25
  2646                              <1> 	;
  2647                              <1> 	;------	SHIFT KEY FOUND
  2648                              <1> K17:
  2649 00000FF1 81EF[49690000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2650 00000FF7 8AA7[50690000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2651 00000FFD B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2652 00000FFF A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2653                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2654                              <1> 	; 05/12/2021
  2655 00001001 7405                <1> 	jz	short K17C
  2656 00001003 E999000000          <1> 	jmp	K23
  2657                              <1> 	;
  2658                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2659                              <1> K17C:
  2660 00001008 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2661 0000100B 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2662                              <1> 	;
  2663                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2664 0000100D 0825[636A0000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2665 00001013 A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2666 00001015 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2667                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2668                              <1> 	; 05/12/2021
  2669 00001017 E901010000          <1> 	jmp	K26
  2670                              <1> K17D:
  2671 0000101C F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2672 0000101F 740B                <1> 	jz 	short K17E		; NO, JUMP
  2673 00001021 0825[666A0000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2674 00001027 E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2675                              <1> K17E:
  2676 0000102C D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2677 0000102E 0825[646A0000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2678 00001034 E9E4000000          <1> 	jmp	K26
  2679                              <1> 	;
  2680                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2681                              <1> K18:					; SHIFT-TOGGLE
  2682 00001039 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2683 0000103C 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2684                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2685                              <1> 	; 05/12/2021
  2686 0000103E E9C2000000          <1> 	jmp	K25
  2687                              <1> K18A:
  2688 00001043 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2689 00001045 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2690 00001047 F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2691 0000104A 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2692                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2693                              <1> 	; 05/12/2021
  2694 0000104C E9B4000000          <1> 	jmp	K25
  2695                              <1> K18B:
  2696 00001051 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2697 00001054 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2698                              <1> K19:	
  2699 00001056 F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2700 00001059 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2701 0000105B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2702 0000105E 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2703                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2704 00001060 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2705 00001062 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2706                              <1> K21:					; MIGHT BE NUMERIC
  2707 00001067 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2708 0000106A 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2709                              <1> 	;
  2710                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2711 0000106C 8425[646A0000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2712                              <1> 	;jnz	K26
  2713                              <1> 	; 05/12/2021
  2714 00001072 7405                <1> 	jz	short K22A
  2715 00001074 E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2716                              <1> K22A:
  2717 00001079 0825[646A0000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2718 0000107F 3025[636A0000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2719                              <1> 	;
  2720                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2721 00001085 F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2722 00001088 7407                <1> 	jz	short K22B		; GO IF NOT
  2723                              <1> 	;
  2724                              <1> 	; 05/12/2021
  2725                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2726 0000108A 50                  <1> 	push	eax
  2727 0000108B E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2728                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2729 00001090 58                  <1> 	pop	eax
  2730                              <1> K22B:
  2731 00001091 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2732                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2733                              <1> 	; 05/12/2021
  2734 00001093 7405                <1> 	je	short K22C
  2735 00001095 E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2736                              <1> K22C:
  2737 0000109A 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2738 0000109C E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2739                              <1> 	;
  2740                              <1> 	;-----	BREAK SHIFT FOUND
  2741                              <1> K23:					; BREAK-SHIFT-FOUND
  2742 000010A1 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2743 000010A4 F6D4                <1> 	not	ah			; INVERT MASK
  2744 000010A6 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2745 000010A8 2025[636A0000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2746 000010AE 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2747 000010B1 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2748                              <1> 	;
  2749 000010B3 F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2750 000010B6 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2751 000010B8 2025[666A0000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2752 000010BE EB08                <1> 	jmp	short K23B		; CONTINUE
  2753                              <1> K23A:
  2754 000010C0 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2755 000010C2 2025[646A0000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2756                              <1> K23B:
  2757 000010C8 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2758 000010CA A0[666A0000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2759 000010CF D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2760 000010D1 0A05[646A0000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2761 000010D7 D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2762 000010D9 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2763 000010DB 0805[636A0000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2764 000010E1 88E0                <1> 	mov	al, ah
  2765                              <1> K23D:
  2766 000010E3 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2767 000010E5 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2768                              <1> 	;	
  2769                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2770 000010E7 A0[676A0000]        <1> 	mov	al, [ALT_INPUT]
  2771 000010EC B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2772 000010EE 8825[676A0000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2773 000010F4 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2774 000010F6 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2775 000010F8 E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2776                              <1> 	;
  2777                              <1> K24:					; BREAK-TOGGLE
  2778 000010FD 2025[646A0000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2779 00001103 EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2780                              <1> 	;
  2781                              <1> 	;-----	TEST FOR HOLD STATE
  2782                              <1> 					; AL, AH = SCAN CODE
  2783                              <1> K25:					; NO-SHIFT-FOUND
  2784 00001105 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2785 00001107 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2786 00001109 F605[646A0000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2787 00001110 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2788 00001112 3C45                <1> 	cmp	al, NUM_KEY
  2789 00001114 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2790 00001116 8025[646A0000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2791                              <1> 	;
  2792                              <1> K26:
  2793 0000111D 8025[666A0000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2794                              <1> K26A:					; INTERRUPT-RETURN
  2795 00001124 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2796 00001125 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2797 00001127 E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2798                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2799 00001129 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2800 0000112B E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2801                              <1> K27A:
  2802 00001130 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2803 00001131 07                  <1> 	pop	es			; RESTORE REGISTERS
  2804 00001132 1F                  <1> 	pop	ds
  2805 00001133 5F                  <1> 	pop	edi
  2806 00001134 5E                  <1> 	pop	esi
  2807 00001135 5A                  <1> 	pop	edx
  2808 00001136 59                  <1> 	pop	ecx
  2809 00001137 5B                  <1> 	pop	ebx
  2810 00001138 58                  <1> 	pop	eax
  2811                              <1> 	;pop	ebp
  2812 00001139 CF                  <1> 	iret				; RETURN
  2813                              <1> 
  2814                              <1> 	;-----	NOT IN	HOLD STATE
  2815                              <1> K28:					; NO-HOLD-STATE
  2816 0000113A 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2817 0000113C 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2818                              <1> 	;
  2819 0000113E F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2820 00001141 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2821                              <1>         ; 05/12/2021
  2822                              <1> 	;jz      K38
  2823                              <1> 	;
  2824 00001143 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2825 00001146 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2826                              <1> 	; 28/02/2015
  2827 00001148 F605[646A0000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2828 0000114F 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2829                              <1> 	; 05/12/2021
  2830                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2831                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2832 00001151 E9D1000000          <1> K28A:	jmp	K38
  2833                              <1> 	;
  2834                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2835                              <1> K29:					; TEST-RESET
  2836 00001156 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2837 00001159 740B                <1> 	jz	short K31		; NO_RESET
  2838 0000115B 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2839 0000115D 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2840                              <1> 	;
  2841                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2842                              <1>  	; 26/08/2014
  2843                              <1> cpu_reset:
  2844                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2845                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2846 0000115F B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2847 00001161 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2848                              <1> khere:
  2849 00001163 F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2850 00001164 EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2851                              <1> 
  2852                              <1> 	;
  2853                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2854                              <1> K31:					; NO-RESET
  2855 00001166 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2856 00001168 7507                <1> 	jne	short K311		; NOT THERE
  2857 0000116A B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2858 0000116C E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2859                              <1> K311:
  2860 00001171 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2861 00001173 7509                <1> 	jne	short K312		; NOT THERE
  2862 00001175 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2863 00001179 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2864                              <1> K312:
  2865 0000117E 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2866 00001180 7471                <1>         je	short K37B              ; GO PROCESS
  2867 00001182 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2868 00001184 746D                <1>         je	short K37B              ; GO PROCESS
  2869                              <1> 	;
  2870                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2871                              <1> K32:					; ALT-KEY-PAD
  2872 00001186 BF[24690000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2873 0000118B B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2874 00001190 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2875 00001192 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2876 00001194 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2877                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2878                              <1> 	; 05/12/2021
  2879 00001197 751C                <1> 	jnz	short K32B
  2880 00001199 81EF[25690000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2881 0000119F A0[676A0000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2882 000011A4 B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2883 000011A6 F6E4                <1> 	mul	ah
  2884 000011A8 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2885 000011AB A2[676A0000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2886                              <1> K32A:
  2887 000011B0 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2888                              <1> K32B:
  2889                              <1> 	; 05/12/2021
  2890 000011B5 EB6A                <1> 	jmp	K37C
  2891                              <1> 	;
  2892                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2893                              <1> K33:					; NO-ALT-KEYPAD
  2894 000011B7 C605[676A0000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2895 000011BE B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2896 000011C3 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2897 000011C5 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2898                              <1> 	;
  2899                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2900                              <1> K34:					; ALT-TOP-ROW
  2901 000011C7 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2902 000011C9 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2903 000011CB 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2904 000011CD 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2905 000011CF 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2906 000011D2 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2907                              <1> 	;
  2908                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2909                              <1> K35:					; ALT-FUNCTION
  2910 000011D4 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2911 000011D6 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2912 000011D8 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2913 000011DA 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2914 000011DC 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2915 000011DF EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2916                              <1> K35A:
  2917 000011E1 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2918 000011E4 7425                <1> 	jz	short K37		; NO, JUMP
  2919 000011E6 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  2920 000011E8 7510                <1>         jne     short K35B              ; NOT THERE
  2921 000011EA 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  2922 000011EE E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  2923                              <1> K37B:
  2924 000011F3 B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  2925 000011F5 E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  2926                              <1> K35B:
  2927 000011FA 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  2928 000011FC 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  2929 000011FE 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  2930 00001200 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  2931                              <1>         ; 05/12/2021
  2932                              <1> 	;jne	K26
  2933 00001202 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  2934 00001206 E99C010000          <1> 	jmp	K57			; BUFFER FILL
  2935                              <1> K37:
  2936 0000120B 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  2937 0000120D 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  2938 0000120F 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  2939                              <1>         ;ja	short K32A		; IF SO, IGNORE
  2940 00001211 0F8706FFFFFF        <1>         ja      K26
  2941 00001217 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  2942                              <1> K37A:
  2943 0000121A B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  2944 0000121C E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  2945                              <1> K37C:
  2946 00001221 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  2947 00001223 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  2948 00001225 EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  2949                              <1> 	;
  2950                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  2951                              <1> K38:					; NOT-ALT-SHIFT
  2952                              <1> 					; BL STILL HAS SHIFT FLAGS
  2953 00001227 F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  2954 0000122A 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  2955                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  2956                              <1> 	; 05/12/2021
  2957 0000122C E9AB000000          <1> 	jmp	K44
  2958                              <1> 	;
  2959                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  2960                              <1> 	;-----	TEST FOR BREAK
  2961                              <1> K38A:
  2962 00001231 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  2963 00001233 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  2964 00001235 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2965 00001238 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  2966 0000123A F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  2967 0000123D 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  2968                              <1> K38B:
  2969 0000123F 8B1D[706A0000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  2970 00001245 891D[746A0000]      <1> 	mov	[BUFFER_TAIL], ebx
  2971 0000124B C605[626A0000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  2972                              <1> 	;
  2973                              <1> 	;-----	ENABLE KEYBOARD
  2974 00001252 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2975 00001254 E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2976                              <1> 	;
  2977                              <1> 	; CTRL+BREAK code here !!!
  2978                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  2979                              <1> 	; 17/10/2015	
  2980 00001259 E82A230000          <1> 	call	ctrlbrk ; control+break subroutine
  2981                              <1> 	;
  2982                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  2983                              <1> 	; 05/12/2021
  2984 0000125E 29C0                <1> 	sub	eax, eax
  2985 00001260 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  2986                              <1> 	;
  2987                              <1> 	;-----	TEST FOR PAUSE
  2988                              <1> K39:					; NO_BREAK
  2989 00001265 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  2990 00001268 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  2991 0000126A 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  2992 0000126C 7533                <1> 	jne	short K41		; NO-PAUSE
  2993                              <1> K39P:
  2994 0000126E 800D[646A0000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  2995                              <1> 	;
  2996                              <1> 	;-----	ENABLE KEYBOARD
  2997 00001275 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  2998 00001277 E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2999                              <1> K39A:
  3000 0000127C B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3001 0000127E E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3002                              <1> 	;
  3003                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3004 00001280 803D[606A0000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3005 00001287 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3006 00001289 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3007 0000128D A0[616A0000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3008 00001292 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3009                              <1> 	;
  3010                              <1> K40:					; PAUSE-LOOP
  3011 00001293 F605[646A0000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3012 0000129A 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3013                              <1> 	;
  3014 0000129C E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3015                              <1>         ;
  3016                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3017                              <1> K41:					; NO-PAUSE
  3018 000012A1 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3019 000012A3 7513                <1> 	jne	short K42		; NOT-KEY-55
  3020 000012A5 F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3021 000012A8 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3022 000012AA F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3023 000012AD 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3024                              <1> K41A:	
  3025 000012AF 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3026 000012B3 E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3027                              <1> 	;
  3028                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3029                              <1> K42:					; NOT-KEY-55
  3030 000012B8 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3031 000012BA 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3032 000012BC 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3033 000012BE 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3034 000012C0 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3035 000012C3 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3036 000012C5 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3037 000012C9 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3038                              <1> K42A:
  3039                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3040 000012CE 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3041                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3042                              <1> 	;;jb	K56 ; 20/02/2015
  3043                              <1> 	;;jmp	K64 ; 20/02/2015
  3044                              <1> K42B:
  3045 000012D0 BB[58690000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3046                              <1> 	;;jmp	K64
  3047                              <1> 	;jb	K56 ;; 20/02/2015	
  3048                              <1> 	; 05/12/2021
  3049 000012D5 7267                <1> 	jb	short K45F
  3050 000012D7 E9B9000000          <1> 	jmp	K64	
  3051                              <1>         ;
  3052                              <1> 	;-----	NOT IN CONTROL SHIFT
  3053                              <1> K44:					; NOT-CTL-SHIFT
  3054 000012DC 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3055 000012DE 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3056 000012E0 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3057 000012E3 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3058 000012E5 F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3059 000012E8 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3060 000012EA EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3061                              <1> K44A:
  3062 000012EC F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3063 000012EF 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3064                              <1> 	;
  3065                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3066                              <1> K44B:
  3067 000012F1 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3068 000012F3 E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3069 000012F8 B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3070 000012FA E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3071                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3072                              <1> 	;PUSH 	BP			; SAVE POINTER
  3073                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3074                              <1> 	;POP	BP			; RESTORE POINTER
  3075 000012FC 8025[666A0000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3076 00001303 E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3077                              <1> 	;
  3078                              <1> 	;-----	HANDLE IN-CORE KEYS
  3079                              <1> K45:					; NOT-PRINT-SCREEN
  3080 00001308 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3081 0000130A 7734                <1> 	ja	short K46		; JUMP IF NOT
  3082 0000130C 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3083 0000130E 7505                <1> 	jne	short K45A		; NO, JUMP
  3084 00001310 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3085 00001313 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3086                              <1> K45A:
  3087 00001315 B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3088 0000131A BF[2E690000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3089 0000131F F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3090                              <1> 		; 20/02/2015
  3091 00001321 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3092                              <1> 	;
  3093 00001323 F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3094 00001326 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3095                              <1> K45B:
  3096 00001328 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3097 0000132B 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3098                              <1> 					; NO, LOWERCASE
  3099                              <1> K45C:
  3100 0000132D BB[B0690000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3101 00001332 EB51                <1> 	jmp	short K56	
  3102                              <1> K45D:					; ALMOST-CAPS-STATE
  3103 00001334 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3104 00001337 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3105                              <1> K45E:
  3106 00001339 BB[086A0000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3107 0000133E EB45                <1> K45F:	jmp	short K56
  3108                              <1> 	;
  3109                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3110                              <1> K46:					; NOT IN-CORE AREA
  3111 00001340 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3112                              <1> 	;ja	short K47		; JUMP IF NOT
  3113                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3114 00001342 7635                <1> 	jna	short K53		
  3115                              <1> 	;
  3116                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3117                              <1> K47:					; NOT F1 - F10
  3118 00001344 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3119 00001346 772D                <1> 	ja	short K52		; JUMP IF NOT
  3120                              <1> 	;
  3121                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3122                              <1> K48:
  3123 00001348 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3124 0000134A 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3125 0000134C 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3126 0000134E 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3127 00001350 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3128 00001353 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3129                              <1> 	;		
  3130 00001355 F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3131 00001358 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3132 0000135A F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3133                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3134 0000135D 75DA                <1> 	jnz	short K45E
  3135                              <1> 	;
  3136                              <1> 	;-----	BASE CASE FOR KEYPAD
  3137                              <1> K49:					
  3138 0000135F 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3139 00001361 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3140 00001363 B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3141 00001365 EB40                <1> 	jmp	short K57		; BUFFER FILL
  3142                              <1> K49A:
  3143 00001367 BB[B0690000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3144 0000136C EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3145                              <1> 	;
  3146                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3147                              <1> K50:					; ALMOST-NUM-STATE
  3148 0000136E F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3149 00001371 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3150 00001373 EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3151                              <1> 	;
  3152                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3153                              <1> K52:					; NOT A NUMPAD KEY
  3154 00001375 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3155                              <1> 	;jne	short K53		; JUMP IF NOT
  3156                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3157 00001377 74AF                <1> 	je	short K45B		
  3158                              <1> 	;
  3159                              <1> 	;-----	MUST BE F11 OR F12 
  3160                              <1> K53:					; F1 - F10 COME HERE, TOO
  3161 00001379 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3162 0000137C 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3163                              <1> 		; 20/02/2015 
  3164 0000137E BB[086A0000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3165 00001383 EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3166                              <1> 	;
  3167                              <1> 	;-----	TRANSLATE THE CHARACTER
  3168                              <1> K56:					; TRANSLATE-CHAR
  3169 00001385 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3170 00001387 D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3171 00001388 F605[666A0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3172 0000138F 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3173 00001391 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3174 00001393 EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3175                              <1> 	;
  3176                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3177                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3178 00001395 FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3179 00001397 D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3180 00001398 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3181 0000139A B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3182 0000139C F605[666A0000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3183 000013A3 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3184 000013A5 B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3185                              <1> 	;
  3186                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3187                              <1> K57:					; BUFFER_FILL
  3188 000013A7 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3189 000013A9 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3190                              <1> 	; 05/12/2021
  3191                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3192 000013AB 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3193                              <1> 	; 05/12/2021
  3194 000013AE 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3195                              <1> 	;je	K26			; INTERRUPT_RETURN
  3196                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3197 000013B0 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3198                              <1> K61:					; NOT-CAPS-STATE
  3199 000013B5 8B1D[746A0000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3200 000013BB 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3201 000013BD E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3202 000013C2 3B1D[706A0000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3203 000013C8 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3204 000013CA 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3205 000013CD 891D[746A0000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3206 000013D3 E945FDFFFF          <1> 	jmp	K26
  3207                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3208                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3209                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3210                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3211                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3212                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3213                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3214                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3215                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3216                              <1> 	;;jmp   K27                    
  3217                              <1> 	;
  3218                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3219                              <1> K62:
  3220 000013D8 B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3221 000013DA E620                <1> 	out	INTA00, al
  3222 000013DC 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3223 000013E0 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3224 000013E2 E89B010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3225 000013E7 E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3226                              <1> 
  3227                              <1> SHIP_IT:
  3228                              <1> 	;---------------------------------------------------------------------------------
  3229                              <1> 	; SHIP_IT
  3230                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3231                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3232                              <1> 	;---------------------------------------------------------------------------------
  3233                              <1> 	;
  3234                              <1> 	;push	ax			; SAVE DATA TO SEND
  3235                              <1> 	; 05/12/2021
  3236 000013EC 50                  <1> 	push	eax
  3237                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3238 000013ED FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3239                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3240 000013EE B900000100          <1> 	mov	ecx, 10000h			
  3241                              <1> S10:
  3242 000013F3 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3243 000013F5 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3244 000013F7 E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3245                              <1> 
  3246                              <1> 	;pop	ax			; GET DATA TO SEND
  3247                              <1> 	; 05/12/2021
  3248 000013F9 58                  <1> 	pop	eax
  3249 000013FA E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3250 000013FC FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3251 000013FD C3                  <1> 	retn				; RETURN TO CALLER
  3252                              <1> 
  3253                              <1> SND_DATA:
  3254                              <1> 	; ---------------------------------------------------------------------------------
  3255                              <1> 	; SND_DATA
  3256                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3257                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3258                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3259                              <1> 	; ---------------------------------------------------------------------------------
  3260                              <1> 	;
  3261                              <1> 	;push	ax			; SAVE REGISTERS
  3262                              <1> 	;push	bx
  3263                              <1> 	; 05/12/2021
  3264 000013FE 50                  <1> 	push	eax
  3265 000013FF 53                  <1> 	push	ebx
  3266 00001400 51                  <1> 	push	ecx
  3267 00001401 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3268 00001403 B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3269                              <1> SD0:
  3270 00001405 FA                  <1> 	cli				; DISABLE INTERRUPTS
  3271 00001406 8025[656A0000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3272                              <1> 	;
  3273                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3274 0000140D B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3275                              <1> SD5:
  3276 00001412 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3277 00001414 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3278 00001416 E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3279                              <1> 	;
  3280 00001418 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3281 0000141A E660                <1> 	out	PORT_A, al		; SEND BYTE
  3282 0000141C FB                  <1> 	sti				; ENABLE INTERRUPTS
  3283                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3284 0000141D B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3285                              <1> SD1:
  3286 00001422 F605[656A0000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3287 00001429 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3288 0000142B E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3289                              <1> SD2:
  3290 0000142D FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3291 0000142F 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3292 00001431 800D[656A0000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3293 00001438 EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3294                              <1> SD3:
  3295 0000143A F605[656A0000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3296 00001441 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3297                              <1> SD4:	
  3298 00001443 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3299                              <1> 	;pop	bx
  3300                              <1> 	;pop	ax
  3301                              <1> 	; 05/12/2021
  3302 00001444 5B                  <1> 	pop	ebx
  3303 00001445 58                  <1> 	pop	eax
  3304 00001446 C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3305                              <1> 
  3306                              <1> SND_LED:
  3307                              <1> 	; ---------------------------------------------------------------------------------
  3308                              <1> 	; SND_LED
  3309                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3310                              <1> 	;
  3311                              <1> 	;----------------------------------------------------------------------------------
  3312                              <1> 	;
  3313 00001447 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3314 00001448 F605[656A0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3315 0000144F 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3316                              <1> 	;
  3317 00001451 800D[656A0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3318 00001458 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3319 0000145A E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3320 0000145C EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3321                              <1> SND_LED1:
  3322 0000145E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3323 0000145F F605[656A0000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3324 00001466 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3325                              <1> 	;
  3326 00001468 800D[656A0000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3327                              <1> SL0:
  3328 0000146F B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3329 00001471 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3330 00001476 FA                  <1> 	cli
  3331 00001477 E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3332 0000147C 8025[656A0000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3333 00001483 0805[656A0000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3334 00001489 F605[656A0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3335 00001490 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3336                              <1> 	;
  3337 00001492 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3338 00001497 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3339 00001498 F605[656A0000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3340 0000149F 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3341                              <1> SL2:
  3342 000014A1 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3343 000014A3 E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3344 000014A8 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3345                              <1> SL3:
  3346 000014A9 8025[656A0000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3347                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3348 000014B0 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3349 000014B1 C3                  <1> 	retn				; RETURN TO CALLER
  3350                              <1> 
  3351                              <1> MAKE_LED:
  3352                              <1> 	;---------------------------------------------------------------------------------
  3353                              <1> 	; MAKE_LED
  3354                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3355                              <1> 	;	THE MODE INDICATORS.
  3356                              <1> 	;---------------------------------------------------------------------------------
  3357                              <1> 	;
  3358                              <1> 	;push 	cx			; SAVE CX
  3359 000014B2 A0[636A0000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3360 000014B7 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3361                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3362                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3363 000014B9 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3364 000014BC 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3365                              <1> 	;pop	cx
  3366 000014BE C3                  <1> 	retn				; RETURN TO CALLER
  3367                              <1> 
  3368                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3369                              <1> 
  3370                              <1> 
  3371                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1802                                  
  1803                                  %include 'video.s' ; 07/03/2015
  1804                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  1805                              <1> ; (re-write kernel for test by using previous version without a major defect)
  1806                              <1> ; ****************************************************************************
  1807                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1808                              <1> ; Last Modification: 05/12/2021
  1809                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1810                              <1> ;
  1811                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1812                              <1> 
  1813                              <1> ; 05/12/2021
  1814                              <1> ; 30/06/2015
  1815                              <1> ; 27/06/2015
  1816                              <1> ; 11/03/2015
  1817                              <1> ; 02/09/2014
  1818                              <1> ; 30/08/2014
  1819                              <1> ; VIDEO FUNCTIONS
  1820                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1821                              <1> 
  1822                              <1> write_tty:
  1823                              <1> 	; 13/08/2015
  1824                              <1> 	; 02/09/2014
  1825                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1826                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1827                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1828                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1829                              <1> 	;
  1830                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1831                              <1> 	;	   AL = Character to be written
  1832                              <1> 	;	   EBX = Video Page (0 to 7)
  1833                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1834                              <1> 
  1835                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1836                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1837                              <1> 
  1838                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1839                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1840                              <1> ;
  1841                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1842                              <1> ;
  1843                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1844                              <1> ;										:
  1845                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1846                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1847                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1848                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1849                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1850                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1851                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1852                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1853                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1854                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1855                              <1> ;   THE 0 COLOR IS USED.							:
  1856                              <1> ;   ENTRY --									:
  1857                              <1> ;     (AH) = CURRENT CRT MODE							:
  1858                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1859                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1860                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1861                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1862                              <1> ;   EXIT -- 									:
  1863                              <1> ;     ALL REGISTERS SAVED							:
  1864                              <1> ;--------------------------------------------------------------------------------
  1865                              <1> 
  1866 000014BF FA                  <1> 	cli
  1867                              <1> 	;
  1868                              <1> 	; READ CURSOR (04/12/2013)
  1869                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1870 000014C0 08FF                <1> 	or	bh, bh
  1871 000014C2 0F85AB000000        <1> 	jnz	beeper
  1872                              <1> 	; 01/09/2014
  1873 000014C8 803D[606A0000]03    <1> 	cmp	byte [CRT_MODE], 3
  1874 000014CF 7405                <1> 	je	short m3
  1875                              <1> 	;
  1876 000014D1 E876020000          <1> 	call	set_mode
  1877                              <1> m3:
  1878 000014D6 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1879 000014D8 66D1E6              <1> 	shl	si, 1
  1880 000014DB 81C6[56700000]      <1> 	add	esi, cursor_posn
  1881 000014E1 668B16              <1> 	mov	dx, [esi]
  1882                              <1> 	;
  1883                              <1> 	; dx now has the current cursor position
  1884                              <1> 	;
  1885 000014E4 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1886 000014E6 764D                <1> 	jbe	short u8
  1887                              <1> 	;
  1888                              <1> 	; write the char to the screen
  1889                              <1> u0:	
  1890                              <1> 	; ah = attribute/color
  1891                              <1> 	; al = character
  1892                              <1> 	; bl = video page number (0 to 7)
  1893                              <1> 	; bh = 0
  1894                              <1> 	;
  1895 000014E8 E832020000          <1> 	call	write_c_current
  1896                              <1> 	;
  1897                              <1> 	; position the cursor for next char
  1898 000014ED FEC2                <1> 	inc	dl		; next column
  1899                              <1> 	;cmp	dl, [CRT_COLS]
  1900 000014EF 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1901 000014F2 0F85E9000000        <1>         jne     set_cpos
  1902 000014F8 B200                <1> 	mov	dl, 0		; column = 0
  1903                              <1> u10:				; (line feed found)
  1904 000014FA 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1905 000014FD 722F                <1> 	jb 	short u6
  1906                              <1> 	;
  1907                              <1> 	; scroll required
  1908                              <1> u1:	
  1909                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1910 000014FF E8DD000000          <1> 	call	set_cpos
  1911                              <1> 	;
  1912                              <1> 	; determine value to fill with during scroll
  1913                              <1> u2:
  1914                              <1> 	; READ_AC_CURRENT		:
  1915                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1916                              <1> 	;    AT THE CURRENT CURSOR POSITION
  1917                              <1> 	;
  1918                              <1> 	; INPUT				
  1919                              <1> 	;	(AH) = CURRENT CRT MODE
  1920                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  1921                              <1> 	;	(DS) = DATA SEGMENT
  1922                              <1> 	;	(ES) = REGEN SEGMENT
  1923                              <1> 	; OUTPUT			
  1924                              <1> 	;	(AL) = CHARACTER READ
  1925                              <1> 	;	(AH) = ATTRIBUTE READ
  1926                              <1> 	;
  1927                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  1928                              <1> 	;
  1929                              <1> 	; bl = video page number
  1930                              <1> 	;
  1931 00001504 E834010000          <1> 	call	find_position	; get regen location and port address
  1932                              <1> 	; dx = status port
  1933                              <1> 	; esi = cursor location/address
  1934                              <1> p11:
  1935 00001509 FB                  <1> 	sti			; enable interrupts
  1936 0000150A 90                  <1> 	nop			; allow for small interupts window
  1937 0000150B FA                  <1> 	cli			; blocks interrupts for single loop
  1938 0000150C EC                  <1> 	in	al, dx		; get status from adapter
  1939 0000150D A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  1940 0000150F 75F8                <1> 	jnz	short p11	; wait until it is
  1941                              <1> p12:				; now wait for either retrace high
  1942 00001511 EC                  <1> 	in	al, dx		; get status
  1943 00001512 A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  1944 00001514 74FB                <1> 	jz	short p12	; wait until either is active	
  1945                              <1> p13:
  1946 00001516 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  1947 0000151C 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  1948                              <1> 	;
  1949                              <1> 	; al = character, ah = attribute
  1950                              <1> 	;
  1951 0000151F FB                  <1> 	sti
  1952                              <1> 	; bl = video page number 	
  1953                              <1> u3:
  1954                              <1> 	;;mov	ax, 0601h 	; scroll one line
  1955                              <1> 	;;sub	cx, cx		; upper left corner
  1956                              <1> 	;;mov	dh, 25-1 	; lower right row
  1957                              <1> 	;;;mov	dl, [CRT_COLS]
  1958                              <1> 	;mov	dl, 80		; lower right column	
  1959                              <1> 	;;dec	dl
  1960                              <1> 	;;mov	dl, 79
  1961                              <1> 
  1962                              <1> 	;;call	scroll_up	; 04/12/2013
  1963                              <1> 	;;; 11/03/2015
  1964                              <1> 	; 02/09/2014
  1965                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  1966                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  1967                              <1> 	; 11/03/2015
  1968 00001520 6629C9              <1> 	sub	cx, cx
  1969 00001523 66BA4F18            <1> 	mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  1970                              <1> 	;
  1971 00001527 B001                <1> 	mov	al, 1		; scroll 1 line up
  1972                              <1> 		; ah = attribute
  1973 00001529 E939010000          <1> 	jmp	scroll_up
  1974                              <1> ;u4:
  1975                              <1> 	;;int	10h		; video-call return
  1976                              <1> 				; scroll up the screen
  1977                              <1> 				; tty return
  1978                              <1> ;u5:
  1979                              <1> 	;retn			; return to the caller
  1980                              <1> 
  1981                              <1> u6:				; set-cursor-inc
  1982 0000152E FEC6                <1> 	inc	dh		; next row
  1983                              <1> 				; set cursor
  1984                              <1> ;u7:					
  1985                              <1> 	;;mov	ah, 02h
  1986                              <1> 	;;jmp	short u4 	; establish the new cursor
  1987                              <1> 	;call	set_cpos
  1988                              <1> 	;jmp 	short u5
  1989 00001530 E9AC000000          <1> 	jmp     set_cpos
  1990                              <1> 
  1991                              <1> 	; check for control characters
  1992                              <1> u8:
  1993 00001535 7438                <1> 	je	short u9
  1994 00001537 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  1995 00001539 74BF                <1> 	je	short u10
  1996 0000153B 3C07                <1> 	cmp	al, 07h 	; is it a bell
  1997 0000153D 7434                <1> 	je	short u11
  1998 0000153F 3C08                <1> 	cmp	al, 08h		; is it a backspace
  1999                              <1> 	;jne	short u0
  2000 00001541 7424                <1> 	je	short bs	; 12/12/2013
  2001                              <1> 	; 12/12/2013 (tab stop)
  2002 00001543 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2003 00001545 75A1                <1> 	jne	short u0
  2004 00001547 88D0                <1> 	mov	al, dl
  2005 00001549 6698                <1> 	cbw
  2006 0000154B B108                <1> 	mov	cl, 8
  2007 0000154D F6F1                <1> 	div	cl
  2008 0000154F 28E1                <1> 	sub	cl, ah
  2009                              <1> ts:
  2010                              <1> 	; 02/09/2014
  2011                              <1> 	; 01/09/2014
  2012 00001551 B020                <1> 	mov	al, 20h
  2013                              <1> tsloop:
  2014 00001553 6651                <1> 	push	cx
  2015 00001555 6650                <1> 	push	ax
  2016 00001557 30FF                <1> 	xor 	bh, bh
  2017                              <1> 	;mov	bl, [active_page]
  2018 00001559 E878FFFFFF          <1> 	call	m3
  2019 0000155E 6658                <1> 	pop	ax  ; ah = attribute/color
  2020 00001560 6659                <1> 	pop	cx
  2021 00001562 FEC9                <1> 	dec	cl
  2022 00001564 75ED                <1> 	jnz	short tsloop
  2023 00001566 C3                  <1> 	retn
  2024                              <1> bs:	
  2025                              <1> 	; back space found
  2026                              <1> 
  2027 00001567 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2028                              <1> 	;je	short u7 	; set_cursor
  2029 00001569 7476                <1> 	jz	short set_cpos
  2030 0000156B 664A                <1> 	dec	dx     		; no -- just move it back
  2031                              <1> 	;jmp	short u7
  2032 0000156D EB72                <1> 	jmp	short set_cpos
  2033                              <1> 
  2034                              <1> 	; carriage return found
  2035                              <1> u9:
  2036 0000156F B200                <1> 	mov	dl, 0 		; move to first column
  2037                              <1> 	;jmp	short u7
  2038 00001571 EB6E                <1> 	jmp	short set_cpos
  2039                              <1> 
  2040                              <1> 	; line feed found
  2041                              <1> ;u10:
  2042                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2043                              <1> ;	jne	short u6 	; no, just set the cursor
  2044                              <1> ;       jmp     u1              ; yes, scroll the screen
  2045                              <1> 
  2046                              <1> beeper: 
  2047                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2048                              <1> 	; 18/01/2014
  2049                              <1> 	; 03/12/2013
  2050                              <1> 	; bell found
  2051                              <1> u11:
  2052 00001573 FB                  <1> 	sti
  2053 00001574 3A1D[66700000]      <1> 	cmp	bl, [active_page]
  2054 0000157A 7551                <1> 	jne	short u12	; Do not sound the beep 
  2055                              <1> 				; if it is not written on the active page
  2056 0000157C 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2057 00001580 B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2058                              <1> 	;call	beep		; sound the pod bell
  2059                              <1> 	;jmp	short u5 	; tty_return
  2060                              <1> 	;retn
  2061                              <1> 	
  2062                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2063                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2064                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2065                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2066                              <1> 
  2067                              <1> beep:
  2068                              <1> 	; 07/02/2015
  2069                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2070                              <1> 	; 18/01/2014
  2071                              <1> 	; 03/12/2013
  2072                              <1> 	;
  2073                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2074                              <1> 	;
  2075                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2076                              <1> 	;
  2077                              <1> 	; ENTRY:
  2078                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2079                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2080                              <1> 	; EXIT:				:
  2081                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2082                              <1> 
  2083 00001582 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2084 00001583 FA                  <1> 	cli			; block interrupts during update
  2085 00001584 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2086 00001586 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2087 00001588 EB00                <1> 	jmp	$+2		; I/O delay
  2088 0000158A 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2089 0000158C E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2090 0000158E EB00                <1> 	jmp	$+2		; I/O delay
  2091 00001590 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2092 00001592 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2093 00001594 E461                <1> 	in	al, PORT_B	; get current setting of port
  2094 00001596 88C4                <1> 	mov	ah, al		; save that setting
  2095 00001598 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2096 0000159A E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2097                              <1> 	;popf	; 18/01/2014
  2098 0000159C FB                  <1> 	sti
  2099                              <1> g7:				; 1/64 second per count (bl)
  2100 0000159D B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2101 000015A2 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2102 000015A7 FECB                <1> 	dec	bl		; (bl) length count expired?
  2103 000015A9 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2104                              <1> 	;
  2105                              <1> 	;pushf			; save interrupt status
  2106 000015AB FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2107 000015AC E461                <1> 	in	al, PORT_B	; get current port value
  2108                              <1>         ;or      al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2109 000015AE 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2110 000015B0 20C4                <1>         and	ah, al		; someone turned them off during beep
  2111 000015B2 88E0                <1> 	mov	al, ah		; recover value of port
  2112                              <1>         ;or      al, not (GATE2+SPK2) ; force speaker data off
  2113 000015B4 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2114 000015B6 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2115                              <1> 	;popf			; restore interrupt flag state
  2116 000015B8 FB                  <1> 	sti
  2117 000015B9 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2118 000015BE E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2119                              <1> 	;pushf			; save interrupt status
  2120 000015C3 FA                  <1> 	cli			; block interrupts during update
  2121 000015C4 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2122 000015C6 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2123 000015C8 08E0                <1> 	or	al, ah		; recover value of port_b
  2124 000015CA E661                <1> 	out	PORT_B, al	; restore speaker status
  2125 000015CC 9D                  <1> 	popf			; restore interrupt flag state
  2126                              <1> u12:	
  2127 000015CD C3                  <1> 	retn
  2128                              <1> 
  2129                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2130                              <1> 
  2131                              <1> WAITF:
  2132                              <1> waitf:
  2133                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2134                              <1> 	; 03/12/2013
  2135                              <1> 	;
  2136                              <1> ;	push ax			; save work register (ah)	
  2137                              <1> ;waitf1:
  2138                              <1> 				; use timer 1 output bits
  2139                              <1> ;	in	al, PORT_B	; read current counter output status
  2140                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2141                              <1> ;	cmp	al, ah		; did it just change
  2142                              <1> ;	je	short waitf1	; wait for a change in output line
  2143                              <1> ;	;
  2144                              <1> ;	mov	ah, al		; save new lflag state
  2145                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2146                              <1> ;	;
  2147                              <1> ;	pop	ax		; restore (ah)
  2148                              <1> ;	retn			; return (cx)=0
  2149                              <1> 
  2150                              <1> ; 05/12/2021 (Retro UNIX 386 v1.2)
  2151                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2152                              <1> ; 17/12/2014 (dsectrm2.s)
  2153                              <1> ; WAITF
  2154                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2155                              <1> ;
  2156                              <1> ;---WAITF-----------------------------------------------------------------------
  2157                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2158                              <1> ; ENTRY:
  2159                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2160                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2161                              <1> ; EXIT:
  2162                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2163                              <1> ;	(CX) = 0	
  2164                              <1> ;-------------------------------------------------------------------------------
  2165                              <1> 
  2166                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2167                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2168                              <1> 
  2169                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2170                              <1> 	;PUSH	AX			; SAVE WORK REGISTER (AH)
  2171                              <1> 	; 05/12/2021
  2172 000015CE 50                  <1> 	push	eax
  2173                              <1> 	; 16/12/2014
  2174                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2175 000015CF D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2176                              <1> ;17/12/2014	
  2177                              <1> ;WAITF1:
  2178                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2179                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2180                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2181                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2182                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2183                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2184                              <1> 	;
  2185                              <1> 	; 17/12/2014
  2186                              <1> 	;
  2187                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2188                              <1> 	;
  2189                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2190                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2191                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2192                              <1> WR_STATE_0:
  2193 000015D1 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2194 000015D3 A810                <1> 	TEST	AL,010H
  2195 000015D5 74FA                <1> 	JZ	SHORT WR_STATE_0
  2196                              <1> WR_STATE_1:
  2197 000015D7 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2198 000015D9 A810                <1> 	TEST	AL,010H
  2199 000015DB 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2200 000015DD E2F2                <1>         LOOP    WR_STATE_0
  2201                              <1> 	;
  2202                              <1> 	;POP	AX			; RESTORE (AH)
  2203                              <1> 	; 05/12/2021
  2204 000015DF 58                  <1> 	pop	eax
  2205 000015E0 C3                  <1> 	RETn				; (CX) = 0
  2206                              <1> 
  2207                              <1> set_cpos:
  2208                              <1> 	; 27/06/2015
  2209                              <1> 	; 01/09/2014
  2210                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2211                              <1> 	;
  2212                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2213                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2214                              <1> 	;
  2215                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2216                              <1> 	;
  2217                              <1> 	; SET_CPOS
  2218                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2219                              <1> 	;	NEW X-Y VALUES PASSED
  2220                              <1> 	; INPUT
  2221                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2222                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2223                              <1> 	; OUTPUT
  2224                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2225                              <1> 	;
  2226 000015E1 0FB6C3              <1>         movzx   eax, bl  ; BL = video page number ; 27/06/2015 (movzx)
  2227 000015E4 D0E0                <1>         shl     al, 1   ; word offset
  2228 000015E6 BE[56700000]        <1> 	mov	esi, cursor_posn
  2229 000015EB 01C6                <1>         add     esi, eax
  2230 000015ED 668916              <1> 	mov	[esi], dx ; save the pointer
  2231 000015F0 381D[66700000]      <1> 	cmp	[active_page], bl
  2232 000015F6 7532                <1> 	jne	short m17
  2233                              <1> 	;call	m18	; CURSOR SET
  2234                              <1> ;m17:			; SET_CPOS_RETURN
  2235                              <1> 	; 01/09/2014
  2236                              <1> ;	retn
  2237                              <1> 		; DX  = row/column
  2238                              <1> m18:
  2239 000015F8 E832000000          <1> 	call	position ; determine location in regen buffer	
  2240 000015FD 668B0D[54700000]    <1> 	mov	cx, [CRT_START]
  2241 00001604 6601C1              <1> 	add	cx, ax  ; add char position in regen buffer
  2242                              <1> 			; to the start address (offset) for this page
  2243 00001607 66D1E9              <1> 	shr	cx, 1	; divide by 2 for char only count
  2244 0000160A B40E                <1> 	mov	ah, 14	; register number for cursor
  2245                              <1> 	;call	m16	; output value to the 6845	
  2246                              <1> 	;retn
  2247                              <1> 
  2248                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2249                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2250                              <1> m16:
  2251 0000160C FA                  <1> 	cli
  2252                              <1> 	;mov	dx, [addr_6845] ; address register
  2253 0000160D 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2254 00001611 88E0                <1> 	mov	al, ah	; get value
  2255 00001613 EE                  <1> 	out	dx, al	; register set
  2256 00001614 6642                <1> 	inc	dx	; data register
  2257 00001616 EB00                <1> 	jmp	$+2	; i/o delay
  2258 00001618 88E8                <1> 	mov	al, ch	; data
  2259 0000161A EE                  <1> 	out	dx, al	
  2260 0000161B 664A                <1> 	dec	dx	
  2261 0000161D 88E0                <1> 	mov	al, ah
  2262 0000161F FEC0                <1> 	inc	al	; point to other data register
  2263 00001621 EE                  <1> 	out	dx, al	; set for second register
  2264 00001622 6642                <1> 	inc	dx
  2265 00001624 EB00                <1> 	jmp	$+2	; i/o delay
  2266 00001626 88C8                <1> 	mov	al, cl	; second data value
  2267 00001628 EE                  <1> 	out	dx, al
  2268 00001629 FB                  <1> 	sti
  2269                              <1> m17:
  2270 0000162A C3                  <1> 	retn
  2271                              <1> 
  2272                              <1> set_ctype:
  2273                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2274                              <1> 	;
  2275                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2276                              <1> 
  2277                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2278                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2279                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2280                              <1> ;          OR NO CURSOR AT ALL
  2281                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2282                              <1> 
  2283                              <1> ;------------------------------------------------
  2284                              <1> ; SET_CTYPE
  2285                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2286                              <1> ; INPUT
  2287                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2288                              <1> ; OUTPUT	
  2289                              <1> ;	NONE
  2290                              <1> ;------------------------------------------------
  2291                              <1> 
  2292 0000162B B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2293                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2294                              <1> 	;call	m16	; output cx register
  2295                              <1> 	;retn
  2296 0000162D EBDD                <1> 	jmp	m16
  2297                              <1> 
  2298                              <1> 
  2299                              <1> position:
  2300                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2301                              <1> 	; 27/06/2015
  2302                              <1> 	; 02/09/2014
  2303                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2304                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2305                              <1> 	;
  2306                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2307                              <1> 	;
  2308                              <1> 	; POSITION
  2309                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2310                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2311                              <1> 	; INPUT
  2312                              <1> 	;	AX = ROW, COLUMN POSITION
  2313                              <1> 	; OUTPUT
  2314                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2315                              <1> 
  2316                              <1> 		; DX = ROW, COLUMN POSITION
  2317                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2318 0000162F 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2319 00001631 B050                <1> 	mov	al, 80   ; determine bytes to row	
  2320 00001633 F6E6                <1> 	mul	dh 	 ; row value
  2321 00001635 30F6                <1> 	xor	dh, dh   ; 0	
  2322 00001637 6601D0              <1> 	add	ax, dx	 ; add column value to the result
  2323                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2324                              <1> 	; 05/12/2021
  2325 0000163A D1E0                <1> 	shl	eax, 1
  2326                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER 
  2327 0000163C C3                  <1> 	retn
  2328                              <1> 
  2329                              <1> find_position:
  2330                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2331                              <1> 	; 27/06/2015
  2332                              <1> 	; 07/09/2014
  2333                              <1> 	; 02/09/2014
  2334                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2335                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2336 0000163D 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2337 00001640 89CE                <1> 	mov	esi, ecx
  2338                              <1> 	;shl	si, 1
  2339 00001642 D1E6                <1> 	shl	esi, 1 ; 05/12/2021
  2340 00001644 668B96[56700000]    <1> 	mov	dx, [esi+cursor_posn]
  2341 0000164B 7409                <1> 	jz	short p21
  2342                              <1> 	;xor	si, si
  2343 0000164D 31F6                <1> 	xor	esi, esi ; 05/12/2021
  2344                              <1> p20:
  2345                              <1> 	;add	si, [CRT_LEN]
  2346 0000164F 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2347 00001654 E2F9                <1> 	loop	p20
  2348                              <1> p21:
  2349 00001656 6621D2              <1> 	and	dx, dx
  2350 00001659 7407                <1> 	jz	short p22
  2351 0000165B E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2352 00001660 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2353                              <1> p22:	
  2354                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2355                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2356                              <1> 	;add	dx, 6	; point at status port
  2357 00001662 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2358                              <1> 	; cx = 0
  2359 00001666 C3                  <1> 	retn
  2360                              <1> 
  2361                              <1> scroll_up:
  2362                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2363                              <1> 	; 16/01/2016
  2364                              <1> 	; 07/09/2014
  2365                              <1> 	; 02/09/2014
  2366                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2367                              <1> 	; 04/04/2014
  2368                              <1> 	; 04/12/2013
  2369                              <1> 	;
  2370                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2371                              <1> 	;
  2372                              <1> 	; SCROLL UP
  2373                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2374                              <1> 	;	ON THE SCREEN
  2375                              <1> 	; INPUT
  2376                              <1> 	;	(AH) = CURRENT CRT MODE
  2377                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2378                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2379                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2380                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2381                              <1> 	;	(DS) = DATA SEGMENT
  2382                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2383                              <1> 	; OUTPUT
  2384                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2385                              <1> 	;
  2386                              <1> 	;	bh = 0  (02/09/2014)
  2387                              <1> 	;
  2388                              <1> 	; ((ah = 3))
  2389                              <1> 	; cl = left upper column
  2390                              <1> 	; ch = left upper row
  2391                              <1> 	; dl = right lower column
  2392                              <1> 	; dh = right lower row
  2393                              <1> 	;
  2394                              <1> 	; al = line count 
  2395                              <1> 	; ah = attribute to be used on blanked line	
  2396                              <1> 	; bl = video page number (0 to 7)
  2397                              <1> 	; 
  2398                              <1> 
  2399                              <1> 	; Test	Line Count
  2400 00001667 08C0                <1> 	or	al, al
  2401 00001669 740C                <1> 	jz	short al_set
  2402 0000166B 88F7                <1> 	mov	bh, dh	; subtract lower row from upper row
  2403 0000166D 28EF                <1> 	sub	bh, ch
  2404 0000166F FEC7                <1> 	inc	bh	; adjust difference by 1
  2405 00001671 38C7                <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2406 00001673 7502                <1> 	jne	short al_set ; if not the we're all set
  2407 00001675 30C0                <1> 	xor	al, al	; otherwise set al to zero
  2408                              <1> al_set:
  2409 00001677 30FF                <1> 	xor	bh, bh	; 0
  2410                              <1> 	;push	ax
  2411 00001679 50                  <1> 	push	eax ; 05/12/2021
  2412                              <1> 	;mov 	esi, [crt_base]
  2413 0000167A BE00800B00          <1>         mov     esi, 0B8000h  
  2414 0000167F 3A1D[66700000]      <1>         cmp     bl, [active_page]
  2415 00001685 750B                <1> 	jne	short n0
  2416                              <1> 	;
  2417 00001687 66A1[54700000]      <1>         mov     ax, [CRT_START]
  2418 0000168D 6601C6              <1>         add     si, ax
  2419 00001690 EB0F                <1>         jmp     short n1
  2420                              <1> n0:
  2421 00001692 20DB                <1>         and     bl, bl
  2422 00001694 740B                <1> 	jz	short n1
  2423 00001696 88D8                <1> 	mov	al, bl
  2424                              <1> n0x:
  2425                              <1>         ;add    si, [CRT_LEN]
  2426                              <1>         ;add    esi, 80*25*2 
  2427 00001698 6681C6A00F          <1>         add     si, 80*25*2
  2428 0000169D FEC8                <1>         dec	al
  2429 0000169F 75F7                <1> 	jnz	short n0x
  2430                              <1> n1:	
  2431                              <1>         ;Scroll position
  2432                              <1> 	;push	dx
  2433                              <1> 	; 05/12/2021
  2434 000016A1 52                  <1> 	push	edx
  2435 000016A2 6689CA              <1> 	mov	dx, cx	; now, upper left position in DX
  2436 000016A5 E885FFFFFF          <1> 	call	position
  2437 000016AA 01C6                <1> 	add	esi, eax
  2438 000016AC 89F7                <1> 	mov	edi, esi
  2439                              <1> 	;pop	dx	; lower right position in DX
  2440 000016AE 5A                  <1> 	pop	edx ; 05/12/2021
  2441 000016AF 6629CA              <1> 	sub	dx, cx
  2442 000016B2 FEC6                <1> 	inc	dh	; dh = #rows 
  2443 000016B4 FEC2                <1> 	inc	dl	; dl = #cols in block
  2444                              <1> 	;pop	ax	; al = line count, ah = attribute
  2445                              <1> 	; 05/12/2021
  2446 000016B6 58                  <1> 	pop	eax	; al = line count, ah = attribute
  2447 000016B7 31C9                <1> 	xor	ecx, ecx
  2448 000016B9 6689C1              <1> 	mov	cx, ax
  2449                              <1> 	;mov	ah, [CRT_COLS]
  2450 000016BC B450                <1> 	mov	ah, 80
  2451 000016BE F6E4                <1> 	mul	ah	; determine offset to from address
  2452 000016C0 6601C0              <1> 	add	ax, ax  ; *2 for attribute byte
  2453                              <1> 	;
  2454                              <1> 	;push	ax	; offset 
  2455                              <1> 	;push	dx
  2456                              <1> 	; 05/12/2021
  2457 000016C3 50                  <1> 	push	eax
  2458 000016C4 52                  <1> 	push	edx
  2459                              <1> 	;
  2460                              <1> 	; 04/04/2014
  2461 000016C5 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2462                              <1> n8:                      ; wait_display_enable
  2463 000016C9 EC                  <1>         in      al, dx   ; get port
  2464 000016CA A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2465 000016CC 74FB                <1> 	jz	short n8 ; wait_display_enable
  2466 000016CE B025                <1> 	mov	al, 25h
  2467 000016D0 B2D8                <1> 	mov	dl, 0D8h ; address control port
  2468 000016D2 EE                  <1> 	out	dx, al	; turn off video during vertical retrace
  2469                              <1> 	;pop	dx	; #rows, #cols
  2470                              <1>        	;pop	ax	; offset
  2471                              <1> 	; 05/12/2021
  2472 000016D3 5A                  <1> 	pop	edx
  2473 000016D4 58                  <1> 	pop	eax
  2474 000016D5 6691                <1> 	xchg	ax, cx	; 
  2475                              <1> 	; ecx = offset, al = line count, ah = attribute
  2476                              <1> ;n9:
  2477 000016D7 08C0                <1> 	or	al, al
  2478 000016D9 7420                <1>         jz      short n3 
  2479 000016DB 01CE                <1>         add     esi, ecx ; from address for scroll
  2480 000016DD 88F7                <1> 	mov	bh, dh  ; #rows in block
  2481 000016DF 28C7                <1> 	sub	bh, al	; #rows to be moved
  2482                              <1> n2:
  2483                              <1> 	; Move rows
  2484 000016E1 88D1                <1> 	mov	cl, dl	; get # of cols to move
  2485 000016E3 56                  <1> 	push	esi
  2486 000016E4 57                  <1> 	push	edi	; save start address
  2487                              <1> n10:
  2488 000016E5 66A5                <1> 	movsw		; move that line on screen
  2489 000016E7 FEC9                <1> 	dec	cl
  2490 000016E9 75FA                <1>         jnz     short n10
  2491 000016EB 5F                  <1> 	pop	edi
  2492 000016EC 5E                  <1> 	pop	esi	; recover addresses
  2493                              <1>         ;mov    cl, [CRT_COLS] 
  2494                              <1> 	;add	cl, cl
  2495                              <1>         ;mov    ecx, 80*2
  2496 000016ED 66B9A000            <1>         mov     cx, 80*2
  2497 000016F1 01CE                <1>         add     esi, ecx  ; next line
  2498 000016F3 01CF                <1>         add     edi, ecx
  2499 000016F5 FECF                <1> 	dec	bh	 ; count of lines to move
  2500 000016F7 75E8                <1> 	jnz	short n2 ; row loop
  2501                              <1> 	; bh = 0
  2502 000016F9 88C6                <1> 	mov	dh, al	 ; #rows	
  2503                              <1> n3:
  2504                              <1> 	; attribute in ah
  2505 000016FB B020                <1> 	mov	al, ' '	 ; fill with blanks
  2506                              <1> n3x:
  2507                              <1> 	; Clear rows
  2508                              <1>                 ; dh =  #rows
  2509 000016FD 88D1                <1>         mov	cl, dl	; get # of cols to clear
  2510 000016FF 57                  <1>         push    edi     ; save address
  2511                              <1> n11:
  2512 00001700 66AB                <1>         stosw           ; store fill character
  2513 00001702 FEC9                <1> 	dec	cl
  2514 00001704 75FA                <1>         jnz     short n11
  2515 00001706 5F                  <1>         pop     edi     ; recover address
  2516                              <1> 	;mov	cl, [CRT_COLS]
  2517                              <1> 	;add	cl, cl
  2518                              <1>         ;mov    ecx, 80*2
  2519 00001707 B1A0                <1>         mov	cl, 80*2
  2520 00001709 01CF                <1>         add     edi, ecx
  2521 0000170B FECE                <1> 	dec	dh
  2522 0000170D 75EE                <1> 	jnz	short n3x ; 16/01/2016
  2523                              <1> 	;
  2524 0000170F 3A1D[66700000]      <1> 	cmp	bl, [active_page]
  2525 00001715 7507                <1> 	jne	short n6
  2526                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2527 00001717 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2528 00001719 66BAD803            <1> 	mov	dx, 03D8h ; always set color card port
  2529 0000171D EE                  <1> 	out	dx, al
  2530                              <1> n6:
  2531 0000171E C3                  <1> 	retn
  2532                              <1> 
  2533                              <1> 
  2534                              <1> write_c_current:
  2535                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2536                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2537                              <1> 	; 18/01/2014
  2538                              <1> 	; 04/12/2013
  2539                              <1> 	;
  2540                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2541                              <1> 	;
  2542                              <1> 	; WRITE_C_CURRENT
  2543                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2544                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2545                              <1> 	; INPUT	
  2546                              <1> 	;	(AH) = CURRENT CRT MODE
  2547                              <1> 	;	(BH) = DISPLAY PAGE
  2548                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2549                              <1> 	;	(AL) = CHAR TO WRITE
  2550                              <1> 	;	(DS) = DATA SEGMENT
  2551                              <1> 	;	(ES) = REGEN SEGMENT
  2552                              <1> 	; OUTPUT
  2553                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2554                              <1> 
  2555 0000171F FA                  <1> 	cli		
  2556                              <1> 	; bl = video page
  2557                              <1> 	; al = character
  2558                              <1> 	; ah = color/attribute
  2559                              <1> 	;push	dx
  2560                              <1> 	;push	ax	; save character & attribute/color
  2561                              <1> 	; 05/12/2021
  2562 00001720 52                  <1> 	push	edx
  2563 00001721 50                  <1> 	push	eax
  2564 00001722 E816FFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2565                              <1> 	; esi = regen location
  2566                              <1> 	; dx = status port
  2567                              <1> 	;
  2568                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2569                              <1> 	;
  2570                              <1> p41:			; wait for horizontal retrace is low or vertical
  2571 00001727 FB                  <1> 	sti		; enable interrupts first
  2572 00001728 3A1D[66700000]      <1>         cmp     bl, [active_page]
  2573 0000172E 7510                <1> 	jne	short p44 
  2574 00001730 FA                  <1> 	cli 		; block interrupts for single loop
  2575 00001731 EC                  <1> 	in	al, dx	; get status from the adapter
  2576 00001732 A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2577 00001734 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2578 00001736 A801                <1> 	test	al, RHRZ ; is horizontal retrace low
  2579 00001738 75ED                <1> 	jnz	short p41 ; wait until it is
  2580                              <1> p42:			;  wait for either retrace high
  2581 0000173A EC                  <1> 	in	al, dx ; get status again
  2582 0000173B A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2583 0000173D 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2584                              <1> p43:	
  2585 0000173F FB                  <1> 	sti
  2586                              <1> p44:
  2587                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2588                              <1> 	; 05/12/2021
  2589 00001740 58                  <1> 	pop	eax
  2590 00001741 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2591                              <1> 				; Retro UNIX 386 v1 feature only!
  2592 00001747 668906              <1> 	mov	[esi], ax
  2593                              <1> 	;pop	dx
  2594                              <1> 	; 05/12/2021
  2595 0000174A 5A                  <1> 	pop	edx
  2596 0000174B C3                  <1> 	retn
  2597                              <1> 
  2598                              <1> set_mode:
  2599                              <1> 	; 16/01/2016
  2600                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2601                              <1> 	;
  2602                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2603                              <1> 
  2604                              <1> ;------------------------------------------------------
  2605                              <1> ; SET MODE					      :
  2606                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2607                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2608                              <1> ; INPUT						      :
  2609                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2610                              <1> ; OUTPUT					      :
  2611                              <1> ;	NONE					      :
  2612                              <1> ;------------------------------------------------------
  2613                              <1> 
  2614 0000174C 57                  <1> 	push	edi ; 16/01/2016
  2615 0000174D 53                  <1> 	push	ebx
  2616 0000174E 52                  <1> 	push	edx
  2617 0000174F 51                  <1> 	push	ecx ; 16/01/2016
  2618 00001750 50                  <1>         push    eax
  2619                              <1> 
  2620                              <1> 	;mov	dx, 03D4h 	; address or color card
  2621 00001751 B003                <1> 	mov	al, 3
  2622                              <1> ;M8:
  2623 00001753 A2[606A0000]        <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2624 00001758 B029                <1> 	mov	al, 29h
  2625                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2626 0000175A 2437                <1> 	and	al, 037h	; video off, save high resolution bit	
  2627                              <1> 	;push	dx  		; save port value
  2628                              <1> 	;add	dx, 4		; point to control register
  2629 0000175C 66BAD803            <1> 	mov	dx, 3D8h
  2630 00001760 EE                  <1> 	out	dx, al		; reset video to off to suppress rolling
  2631                              <1> 	;pop	dx
  2632                              <1> ;M9:
  2633 00001761 BB[986A0000]        <1> 	mov	ebx, video_params ; initialization table
  2634                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2635                              <1> 	;xchg 	ah, al
  2636                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2637 00001766 30E4                <1> 	xor	ah, ah		  ; ah is register number during loop 
  2638                              <1> 	
  2639                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2640 00001768 B910000000          <1> 	mov	ecx, 16 ; 16/01/2016
  2641                              <1> M10:			;  initialization loop
  2642 0000176D 88E0                <1> 	mov	al, ah 	; get 6845 register number
  2643 0000176F EE                  <1> 	out	dx, al
  2644 00001770 6642                <1> 	inc	dx      ; point to data port
  2645 00001772 FEC4                <1> 	inc	ah	; next register value
  2646 00001774 8A03                <1> 	mov	al, [ebx] ; get table value
  2647 00001776 EE                  <1> 	out	dx, al	; out to chip
  2648 00001777 43                  <1> 	inc	ebx	; next in table
  2649 00001778 664A                <1> 	dec	dx	; back to pointer register
  2650 0000177A E2F1                <1> 	loop	M10	; do the whole table
  2651                              <1> 	
  2652                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2653                              <1> 	;xor	ax, ax  
  2654                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2655                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2656                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2657                              <1> 	; black background, light gray characeter color, space character
  2658                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2659                              <1> ;M13:			  ; clear buffer
  2660                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2661                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2662                              <1> 
  2663                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2664                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2665                              <1> 			 ; prepare to output to video enable port
  2666                              <1> 	;add	dx,4	 ; point to the mode control gerister
  2667 0000177C 66BAD803            <1> 	mov	dx, 3D8h
  2668                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2669 00001780 B029                <1> 	mov	al, 29h
  2670 00001782 EE                  <1> 	out	dx, al	 ; set video enable port
  2671                              <1> 
  2672                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2673                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2674                              <1> 	;
  2675                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2676                              <1> 	;
  2677                              <1> ;-----	SET CURSOR POSITIONS
  2678                              <1> 	;push	edi
  2679                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2680 00001783 BF[56700000]        <1> 	mov	edi, cursor_posn
  2681 00001788 B904000000          <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2682 0000178D 31C0                <1> 	xor	eax, eax
  2683 0000178F F3AB                <1> 	rep 	stosd	; fill with zeroes
  2684                              <1> 	;pop	edi
  2685                              <1> 
  2686                              <1> ;-----	SET UP OVERSCAN REGISTER
  2687 00001791 6642                <1> 	inc	dx	; set overscan port to a default
  2688 00001793 B030                <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2689                              <1> ;M14:
  2690 00001795 EE                  <1> 	out	dx, al	; output the correct value to 3D9 port
  2691                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2692                              <1> 
  2693                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2694                              <1> 	;
  2695 00001796 58                  <1> 	pop	eax
  2696 00001797 59                  <1> 	pop	ecx ; 16/01/2016
  2697 00001798 5A                  <1> 	pop	edx
  2698 00001799 5B                  <1> 	pop	ebx
  2699 0000179A 5F                  <1> 	pop	edi ; 16/01/2016
  2700 0000179B C3                  <1> 	retn
  2701                              <1> 	
  2702                              <1> tty_sw:
  2703                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2704                              <1> 	; 30/06/2015
  2705                              <1> 	; 27/06/2015 
  2706                              <1> 	; 07/09/2014
  2707                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2708                              <1> 	;
  2709                              <1> 	; (Modified registers : EAX)
  2710                              <1> 	;
  2711                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2712                              <1> 	;
  2713                              <1> ;act_disp_page:
  2714                              <1> 	; 30/06/2015
  2715                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2716                              <1> 	; 10/12/2013
  2717                              <1> 	; 04/12/2013
  2718                              <1> 	;
  2719                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2720                              <1> 	;
  2721                              <1> 	; ACT_DISP_PAGE
  2722                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2723                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2724                              <1> 	; INPUT
  2725                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2726                              <1> 	; OUTPUT
  2727                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2728                              <1> 
  2729                              <1> 	;cli
  2730                              <1> 
  2731 0000179C 53                  <1> 	push	ebx
  2732                              <1> 	;push	cx
  2733                              <1> 	;push	dx
  2734                              <1> 	; 05/12/2021
  2735 0000179D 51                  <1> 	push	ecx
  2736 0000179E 52                  <1> 	push	edx
  2737                              <1> 	;
  2738 0000179F A2[66700000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2739                              <1> 	;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2740 000017A4 66B9A00F            <1> 	mov	cx, 25*80*2
  2741                              <1> 	; 27/06/2015
  2742 000017A8 0FB6D8              <1> 	movzx	ebx, al
  2743                              <1> 	;
  2744 000017AB 6698                <1> 	cbw	; 07/09/2014 (ah=0)
  2745 000017AD 66F7E1              <1> 	mul 	cx	; display page times regen length
  2746                              <1> 	; 10/12/2013
  2747 000017B0 66A3[54700000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2748 000017B6 6689C1              <1> 	mov	cx, ax ; start address to cx
  2749                              <1> 	;sar	cx, 1
  2750 000017B9 66D1E9              <1> 	shr	cx, 1	; divide by 2 for 6845 handling
  2751 000017BC B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2752 000017BE E849FEFFFF          <1> 	call	m16
  2753                              <1> 	;sal	bx, 1
  2754                              <1> 	; 01/09/2014
  2755 000017C3 D0E3                <1> 	shl	bl, 1	; *2 for word offset
  2756 000017C5 81C3[56700000]      <1> 	add	ebx, cursor_posn
  2757 000017CB 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2758 000017CE E825FEFFFF          <1> 	call	m18
  2759                              <1> 	;
  2760                              <1> 	;pop	dx
  2761                              <1> 	;pop	cx
  2762                              <1> 	; 05/12/2021
  2763 000017D3 5A                  <1> 	pop	edx
  2764 000017D4 59                  <1> 	pop	ecx
  2765 000017D5 5B                  <1> 	pop	ebx
  2766                              <1> 	;
  2767                              <1> 	;sti
  2768                              <1> 	;
  2769 000017D6 C3                  <1> 	retn
  2770                              <1> 
  2771                              <1> ; % include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2772                              <1> 
  2773                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1804                                  
  1805                                  setup_rtc_int:
  1806                                  ; source: http://wiki.osdev.org/RTC
  1807 000017D7 FA                      	cli		; disable interrupts
  1808                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1809                                  	; in order to change this ...
  1810                                  	; frequency = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1811                                  	; (rate must be above 2 and not over 15)
  1812                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1813 000017D8 B08A                    	mov	al, 8Ah 
  1814 000017DA E670                    	out	70h, al ; set index to register A, disable NMI
  1815 000017DC 90                      	nop
  1816 000017DD E471                    	in	al, 71h ; get initial value of register A
  1817 000017DF 88C4                    	mov 	ah, al
  1818 000017E1 80E4F0                  	and	ah, 0F0h
  1819 000017E4 B08A                    	mov	al, 8Ah 
  1820 000017E6 E670                    	out	70h, al ; reset index to register A
  1821 000017E8 88E0                    	mov	al, ah
  1822 000017EA 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1823 000017EC E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1824                                  	; enable RTC interrupt
  1825 000017EE B08B                    	mov	al, 8Bh ;
  1826 000017F0 E670                    	out	70h, al ; select register B and disable NMI
  1827 000017F2 90                      	nop
  1828 000017F3 E471                    	in	al, 71h ; read the current value of register B
  1829 000017F5 88C4                    	mov	ah, al  ;
  1830 000017F7 B08B                    	mov 	al, 8Bh ;
  1831 000017F9 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1832 000017FB 88E0                    	mov	al, ah  ;
  1833 000017FD 0C40                    	or	al, 40h ;
  1834 000017FF E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1835 00001801 FB                      	sti
  1836 00001802 C3                      	retn
  1837                                  
  1838                                  ; Write memory information
  1839                                  ; Temporary Code
  1840                                  ; 06/11/2014
  1841                                  ; 14/08/2015 
  1842                                  memory_info:	
  1843 00001803 A1[3C700000]            	mov	eax, [memory_size] ; in pages
  1844 00001808 50                      	push	eax
  1845 00001809 C1E00C                  	shl	eax, 12		   ; in bytes
  1846 0000180C BB0A000000              	mov	ebx, 10
  1847 00001811 89D9                    	mov	ecx, ebx	   ; 10
  1848 00001813 BE[A16C0000]            	mov	esi, mem_total_b_str	
  1849 00001818 E8B2000000              	call	bintdstr
  1850 0000181D 58                      	pop	eax
  1851 0000181E B107                    	mov	cl, 7
  1852 00001820 BE[C56C0000]            	mov	esi, mem_total_p_str
  1853 00001825 E8A5000000              	call	bintdstr	
  1854                                  	; 14/08/2015
  1855 0000182A E8BD000000              	call	calc_free_mem
  1856                                  	; edx = calculated free pages
  1857                                  	; ecx = 0
  1858 0000182F A1[40700000]            	mov 	eax, [free_pages]
  1859 00001834 39D0                    	cmp	eax, edx ; calculated free mem value 
  1860                                  		; and initial free mem value are same or not?
  1861 00001836 751D                    	jne 	short pmim ; print mem info with '?' if not
  1862 00001838 52                      	push 	edx ; free memory in pages	
  1863                                  	;mov 	eax, edx
  1864 00001839 C1E00C                  	shl	eax, 12 ; convert page count
  1865                                  			; to byte count
  1866 0000183C B10A                    	mov	cl, 10
  1867 0000183E BE[E56C0000]            	mov	esi, free_mem_b_str
  1868 00001843 E887000000              	call	bintdstr
  1869 00001848 58                      	pop	eax
  1870 00001849 B107                    	mov	cl, 7
  1871 0000184B BE[096D0000]            	mov	esi, free_mem_p_str
  1872 00001850 E87A000000              	call	bintdstr
  1873                                  pmim:
  1874 00001855 BE[8F6C0000]            	mov	esi, msg_memory_info
  1875                                  pmim_nb:	
  1876 0000185A AC                      	lodsb
  1877 0000185B 08C0                    	or	al, al
  1878 0000185D 740D                    	jz	short pmim_ok
  1879 0000185F 56                      	push	esi
  1880 00001860 31DB                    	xor	ebx, ebx ; 0
  1881                                  			; Video page 0 (bl=0)
  1882 00001862 B407                    	mov	ah, 07h ; Black background, 
  1883                                  			; light gray forecolor
  1884 00001864 E856FCFFFF              	call	write_tty
  1885 00001869 5E                      	pop	esi
  1886 0000186A EBEE                    	jmp	short pmim_nb
  1887                                  pmim_ok:
  1888 0000186C C3                      	retn
  1889                                  
  1890                                  ; Convert binary number to hexadecimal string
  1891                                  ; 10/05/2015  
  1892                                  ; dsectpm.s (28/02/2015)
  1893                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1894                                  ; 01/12/2014
  1895                                  ; 25/11/2014
  1896                                  ;
  1897                                  bytetohex:
  1898                                  	; INPUT ->
  1899                                  	; 	AL = byte (binary number)
  1900                                  	; OUTPUT ->
  1901                                  	;	AX = hexadecimal string
  1902                                  	;
  1903 0000186D 53                      	push	ebx
  1904 0000186E 31DB                    	xor	ebx, ebx
  1905 00001870 88C3                    	mov	bl, al
  1906 00001872 C0EB04                  	shr	bl, 4
  1907 00001875 8A9B[BF180000]          	mov	bl, [ebx+hexchrs] 	 	
  1908 0000187B 86D8                    	xchg	bl, al
  1909 0000187D 80E30F                  	and	bl, 0Fh
  1910 00001880 8AA3[BF180000]          	mov	ah, [ebx+hexchrs] 
  1911 00001886 5B                      	pop	ebx	
  1912 00001887 C3                      	retn
  1913                                  
  1914                                  wordtohex:
  1915                                  	; INPUT ->
  1916                                  	; 	AX = word (binary number)
  1917                                  	; OUTPUT ->
  1918                                  	;	EAX = hexadecimal string
  1919                                  	;
  1920 00001888 53                      	push	ebx
  1921 00001889 31DB                    	xor	ebx, ebx
  1922 0000188B 86E0                    	xchg	ah, al
  1923 0000188D 6650                    	push	ax
  1924 0000188F 88E3                    	mov	bl, ah
  1925 00001891 C0EB04                  	shr	bl, 4
  1926 00001894 8A83[BF180000]          	mov	al, [ebx+hexchrs] 	 	
  1927 0000189A 88E3                    	mov	bl, ah
  1928 0000189C 80E30F                  	and	bl, 0Fh
  1929 0000189F 8AA3[BF180000]          	mov	ah, [ebx+hexchrs]
  1930 000018A5 C1E010                  	shl	eax, 16
  1931 000018A8 6658                    	pop	ax
  1932 000018AA 5B                      	pop	ebx
  1933 000018AB EBC0                    	jmp	short bytetohex
  1934                                  	;mov	bl, al
  1935                                  	;shr	bl, 4
  1936                                  	;mov	bl, [ebx+hexchrs] 	 	
  1937                                  	;xchg	bl, al	 	
  1938                                  	;and	bl, 0Fh
  1939                                  	;mov	ah, [ebx+hexchrs] 
  1940                                  	;pop	ebx	
  1941                                  	;retn
  1942                                  
  1943                                  dwordtohex:
  1944                                  	; INPUT ->
  1945                                  	; 	EAX = dword (binary number)
  1946                                  	; OUTPUT ->
  1947                                  	;	EDX:EAX = hexadecimal string
  1948                                  	;
  1949 000018AD 50                      	push	eax
  1950 000018AE C1E810                  	shr	eax, 16
  1951 000018B1 E8D2FFFFFF              	call	wordtohex
  1952 000018B6 89C2                    	mov	edx, eax
  1953 000018B8 58                      	pop	eax
  1954 000018B9 E8CAFFFFFF              	call	wordtohex
  1955 000018BE C3                      	retn
  1956                                  
  1957                                  ; 10/05/2015
  1958                                  hex_digits:
  1959                                  hexchrs:
  1960 000018BF 303132333435363738-     	db '0123456789ABCDEF'
  1960 000018C8 39414243444546     
  1961                                  
  1962                                  ; Convert binary number to decimal/numeric string
  1963                                  ; 06/11/2014
  1964                                  ; Temporary Code
  1965                                  ;
  1966                                  
  1967                                  bintdstr:
  1968                                  	; EAX = binary number
  1969                                  	; ESI = decimal/numeric string address
  1970                                  	; EBX = divisor (10)
  1971                                  	; ECX = string length (<=10)
  1972 000018CF 01CE                    	add	esi, ecx
  1973                                  btdstr0:
  1974 000018D1 4E                      	dec	esi
  1975 000018D2 31D2                    	xor	edx, edx
  1976 000018D4 F7F3                    	div	ebx
  1977 000018D6 80C230                  	add	dl, 30h
  1978 000018D9 8816                    	mov	[esi], dl
  1979 000018DB FEC9                    	dec	cl
  1980 000018DD 740C                    	jz	btdstr2
  1981 000018DF 09C0                    	or	eax, eax
  1982 000018E1 75EE                    	jnz	short btdstr0
  1983                                  btdstr1:
  1984 000018E3 4E                      	dec	esi
  1985 000018E4 C60620                          mov     byte [esi], 20h ; blank space
  1986 000018E7 FEC9                    	dec	cl
  1987 000018E9 75F8                    	jnz	short btdstr1
  1988                                  btdstr2:
  1989 000018EB C3                      	retn
  1990                                  
  1991                                  ; Calculate free memory pages on M.A.T.
  1992                                  ; 06/11/2014
  1993                                  ; Temporary Code
  1994                                  ;
  1995                                  
  1996                                  calc_free_mem:
  1997 000018EC 31D2                    	xor	edx, edx
  1998                                  	;xor	ecx, ecx
  1999 000018EE 668B0D[50700000]        	mov	cx, [mat_size] ; in pages
  2000 000018F5 C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2001 000018F8 BE00001000              	mov	esi, MEM_ALLOC_TBL
  2002                                  cfm0:
  2003 000018FD AD                      	lodsd
  2004 000018FE 51                      	push	ecx
  2005 000018FF B920000000              	mov	ecx, 32
  2006                                  cfm1:
  2007 00001904 D1E8                    	shr	eax, 1
  2008 00001906 7301                    	jnc	short cfm2
  2009 00001908 42                      	inc	edx
  2010                                  cfm2:
  2011 00001909 E2F9                    	loop	cfm1
  2012 0000190B 59                      	pop	ecx
  2013 0000190C E2EF                    	loop	cfm0
  2014 0000190E C3                      	retn
  2015                                  
  2016                                  %include 'diskio.s'  ; 07/03/2015
  2017                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2018                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2019                              <1> ; ****************************************************************************
  2020                              <1> ; Retro UNIX 386 v1 Kernel - DISKIO.INC
  2021                              <1> ; Last Modification: 05/12/2021
  2022                              <1> ;
  2023                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2024                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2025                              <1> 
  2026                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2027                              <1> 
  2028                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2029                              <1> 
  2030                              <1> ; 06/02/2015
  2031                              <1> diskette_io:
  2032 0000190F 9C                  <1> 	pushfd
  2033 00001910 0E                  <1> 	push 	cs
  2034 00001911 E809000000          <1> 	call 	DISKETTE_IO_1
  2035 00001916 C3                  <1> 	retn
  2036                              <1> 	
  2037                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2038                              <1> ;//////////////////////////////////////////////////////
  2039                              <1> 
  2040                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2041                              <1> ; 20/02/2015
  2042                              <1> ; 06/02/2015 (unix386.s)
  2043                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2044                              <1> ;
  2045                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2046                              <1> ;
  2047                              <1> ; ADISK.EQU
  2048                              <1> 
  2049                              <1> ;----- Wait control constants 
  2050                              <1> 
  2051                              <1> ;amount of time to wait while RESET is active.
  2052                              <1> 
  2053                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2054                              <1> 					;at 250 KBS xfer rate.
  2055                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2056                              <1> 
  2057                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2058                              <1> 					;status register to become valid
  2059                              <1> 					;before re-reading.
  2060                              <1> 
  2061                              <1> ;After sending a byte to NEC, status register may remain
  2062                              <1> ;incorrectly set for 24 us.
  2063                              <1> 
  2064                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2065                              <1> 					;RQM low.
  2066                              <1> 
  2067                              <1> ; COMMON.MAC
  2068                              <1> ;
  2069                              <1> ;	Timing macros
  2070                              <1> ;
  2071                              <1> 
  2072                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2073                              <1> 		jmp short $+2
  2074                              <1> %endmacro		
  2075                              <1> 
  2076                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2077                              <1> 		jmp short $+2
  2078                              <1> 		jmp short $+2
  2079                              <1> %endmacro
  2080                              <1> 
  2081                              <1> %macro		NEWIODELAY 0
  2082                              <1> 		out	0EBh,al
  2083                              <1> %endmacro 
  2084                              <1> 
  2085                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2086                              <1> ;;; WAIT_FOR_MEM
  2087                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2088                              <1> ;WAIT_FDU_INT_HI	equ	1
  2089                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2090                              <1> ;;; WAIT_FOR_PORT
  2091                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2092                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2093                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2094                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2095                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2096                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2097                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2098                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2099                              <1> ;;; WAIT_REFRESH
  2100                              <1> ;amount of time to wait for head settle, per unit in parameter
  2101                              <1> ;table = 1 ms.
  2102                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2103                              <1> 
  2104                              <1> 
  2105                              <1> ; //////////////// DISKETTE I/O ////////////////
  2106                              <1> 
  2107                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2108                              <1> 
  2109                              <1> ;----------------------------------------
  2110                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2111                              <1> ;----------------------------------------
  2112                              <1> 
  2113                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2114                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2115                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2116                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2117                              <1> 
  2118                              <1> ;----------------------------------------
  2119                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2120                              <1> ;-------------------------------------------------------------------------------
  2121                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2122                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2123                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2124                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2125                              <1> 
  2126                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2127                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2128                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2129                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2130                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2131                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2132                              <1> 
  2133                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2134                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2135                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2136                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2137                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2138                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2139                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2140                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2141                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2142                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2143                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2144                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2145                              <1> 
  2146                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2147                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2148                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2149                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2150                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2151                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2152                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2153                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2154                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2155                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2156                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2157                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2158                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2159                              <1> 
  2160                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2161                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2162                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2163                              <1> 
  2164                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2165                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2166                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2167                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2168                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2169                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2170                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2171                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2172                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2173                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2174                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2175                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2176                              <1> 
  2177                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2178                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2179                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2180                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2181                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2182                              <1> 
  2183                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2184                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2185                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2186                              <1> INTA01		EQU	021H		; 8259 PORT
  2187                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2188                              <1> INTB01		EQU	0A1H		;
  2189                              <1> 
  2190                              <1> ;-------------------------------------------------------------------------------
  2191                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2192                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2193                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2194                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2195                              <1> ;-------------------------------------------------------------------------------
  2196                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2197                              <1> 
  2198                              <1> ;-------------------------------------------------------------------------------
  2199                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2200                              <1> 
  2201                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2202                              <1> ; (unix386.s <-- dsectrm2.s)
  2203                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2204                              <1> 
  2205                              <1> ; 10/12/2014
  2206                              <1> ;
  2207                              <1> ;int40h:
  2208                              <1> ;	pushf
  2209                              <1> ;	push 	cs
  2210                              <1> ;	;cli
  2211                              <1> ;	call 	DISKETTE_IO_1
  2212                              <1> ;	retn
  2213                              <1> 
  2214                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2215                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2216                              <1> ;
  2217                              <1> 
  2218                              <1> ;-- INT13H ---------------------------------------------------------------------
  2219                              <1> ; DISKETTE I/O
  2220                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2221                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2222                              <1> ; INPUT
  2223                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2224                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2225                              <1> ;		ON ALL DRIVES
  2226                              <1> ;------------------------------------------------------------------------------- 
  2227                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2228                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2229                              <1> ;-------------------------------------------------------------------------------
  2230                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2231                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2232                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2233                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2234                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2235                              <1> ;		320/360	320/360	    0-39
  2236                              <1> ;		320/360	1.2M	    0-39
  2237                              <1> ;		1.2M	1.2M	    0-79
  2238                              <1> ;		720K	720K	    0-79
  2239                              <1> ;		1.44M	1.44M	    0-79	
  2240                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2241                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2242                              <1> ;		320/360	320/360	     1-8/9
  2243                              <1> ;		320/360	1.2M	     1-8/9
  2244                              <1> ;		1.2M	1.2M	     1-15
  2245                              <1> ;		720K	720K	     1-9
  2246                              <1> ;		1.44M	1.44M	     1-18		
  2247                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2248                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2249                              <1> ;		320/360	320/360	        8/9
  2250                              <1> ;		320/360	1.2M	        8/9
  2251                              <1> ;		1.2M	1.2M		15
  2252                              <1> ;		720K	720K		9
  2253                              <1> ;		1.44M	1.44M		18
  2254                              <1> ;
  2255                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2256                              <1> ;
  2257                              <1> ;-------------------------------------------------------------------------------
  2258                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2259                              <1> ;-------------------------------------------------------------------------------
  2260                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2261                              <1> ;-------------------------------------------------------------------------------
  2262                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2263                              <1> ;-------------------------------------------------------------------------------
  2264                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2265                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2266                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2267                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2268                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2269                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2270                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2271                              <1> ;		READ/WRITE ACCESS.
  2272                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2273                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2274                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2275                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2276                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2277                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2278                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2279                              <1> ;
  2280                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2281                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2282                              <1> ;		---------------------------------------------
  2283                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2284                              <1> ;		---------------------------------------------
  2285                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2286                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2287                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2288                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2289                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2290                              <1> ;		---------------------------------------------
  2291                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2292                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2293                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2294                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2295                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2296                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2297                              <1> ;-------------------------------------------------------------------------------
  2298                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2299                              <1> ;	REGISTERS
  2300                              <1> ;	  INPUT
  2301                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2302                              <1> ;	  OUTPUT
  2303                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2304                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2305                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2306                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2307                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2308                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2309                              <1> ;	    (BH) - 0
  2310                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2311                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2312                              <1> ;	    (AX) - 0
  2313                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2314                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2315                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2316                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2317                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2318                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2319                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2320                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2321                              <1> ;-------------------------------------------------------------------------------
  2322                              <1> ;	(AH)= 15H  READ DASD TYPE
  2323                              <1> ;	OUTPUT REGISTERS
  2324                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2325                              <1> ;		00 - DRIVE NOT PRESENT	
  2326                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2327                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2328                              <1> ;		03 - RESERVED (FIXED DISK)
  2329                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2330                              <1> ;-------------------------------------------------------------------------------
  2331                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2332                              <1> ;	OUTPUT REGISTERS
  2333                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2334                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2335                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2336                              <1> ;-------------------------------------------------------------------------------
  2337                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2338                              <1> ;	INPUT REGISTERS
  2339                              <1> ;	(AL) -	00 - NOT USED	
  2340                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2341                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2342                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2343                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2344                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2345                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2346                              <1> ;-------------------------------------------------------------------------------
  2347                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2348                              <1> ;	INPUT REGISTERS
  2349                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2350                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2351                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2352                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2353                              <1> ;	OUTPUT REGISTERS:
  2354                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2355                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2356                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2357                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2358                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2359                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2360                              <1> ;-------------------------------------------------------------------------------
  2361                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2362                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2363                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2364                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2365                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2366                              <1> ;		CHANGE ERROR CODE
  2367                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2368                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2369                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2370                              <1> ;
  2371                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2372                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2373                              <1> ;-------------------------------------------------------------------------------
  2374                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2375                              <1> ;	AH = STATUS OF OPERATION
  2376                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2377                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2378                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2379                              <1> ;		TYPE AH=(15)).
  2380                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2381                              <1> ;	FOR READ/WRITE/VERIFY
  2382                              <1> ;		DS,BX,DX,CX PRESERVED
  2383                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2384                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2385                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2386                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2387                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2388                              <1> ;-------------------------------------------------------------------------------
  2389                              <1> ;
  2390                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2391                              <1> ;
  2392                              <1> ;   -----------------------------------------------------------------
  2393                              <1> ;   |       |       |       |       |       |       |       |       |
  2394                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2395                              <1> ;   |       |       |       |       |       |       |       |       |
  2396                              <1> ;   -----------------------------------------------------------------
  2397                              <1> ;	|	|	|	|	|	|	|	|
  2398                              <1> ;	|	|	|	|	|	-----------------
  2399                              <1> ;	|	|	|	|	|		|
  2400                              <1> ;	|	|	|	|    RESERVED		|
  2401                              <1> ;	|	|	|	|		  PRESENT STATE
  2402                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2403                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2404                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2405                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2406                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2407                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2408                              <1> ;	|	|	|	|	110: RESERVED
  2409                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2410                              <1> ;	|	|	|	|
  2411                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2412                              <1> ;	|	|	|
  2413                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2414                              <1> ;	|	|			DRIVE)
  2415                              <1> ;	|	|
  2416                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2417                              <1> ;
  2418                              <1> ;						00: 500 KBS
  2419                              <1> ;						01: 300 KBS
  2420                              <1> ;						10: 250 KBS
  2421                              <1> ;						11: RESERVED
  2422                              <1> ;
  2423                              <1> ;
  2424                              <1> ;-------------------------------------------------------------------------------
  2425                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2426                              <1> ;-------------------------------------------------------------------------------
  2427                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2428                              <1> ;-------------------------------------------------------------------------------
  2429                              <1> 
  2430                              <1> struc MD
  2431 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2432 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2433 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2434 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2435 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2436 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2437 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2438 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2439 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2440 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2441 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2442 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2443 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2444                              <1> endstruc
  2445                              <1> 
  2446                              <1> BIT7OFF	EQU	7FH
  2447                              <1> BIT7ON	EQU	80H
  2448                              <1> 
  2449                              <1> ;;int13h: ; 16/02/2015
  2450                              <1> ;; 16/02/2015 - 21/02/2015
  2451                              <1> int40h:
  2452 00001917 9C                  <1> 	pushfd
  2453 00001918 0E                  <1> 	push 	cs
  2454 00001919 E801000000          <1> 	call 	DISKETTE_IO_1
  2455 0000191E C3                  <1> 	retn	
  2456                              <1> 
  2457                              <1> DISKETTE_IO_1:
  2458                              <1> 
  2459 0000191F FB                  <1> 	STI				; INTERRUPTS BACK ON
  2460 00001920 55                  <1> 	PUSH	eBP			; USER REGISTER
  2461 00001921 57                  <1> 	PUSH	eDI			; USER REGISTER
  2462 00001922 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2463 00001923 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2464 00001924 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2465 00001925 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2466                              <1> 					; [BP]   = SECTOR #
  2467                              <1> 					; [BP+1] = TRACK #
  2468                              <1> 					; [BP+2] = BUFFER OFFSET
  2469                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2470                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2471                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2472                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2473                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2474                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2475                              <1> 					; BH/[BP+3] = 0
  2476                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2477                              <1> 					; DH/[BP+5] = MAX HEAD #
  2478                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2479 00001927 06                  <1> 	push	es ; 06/02/2015	
  2480 00001928 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2481 00001929 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2482                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2483                              <1> 	;mov	cx, cs
  2484                              <1> 	;mov	ds, cx
  2485 0000192A 66B91000            <1> 	mov	cx, KDATA
  2486 0000192E 8ED9                <1>         mov     ds, cx
  2487 00001930 8EC1                <1>         mov     es, cx
  2488                              <1> 
  2489                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2490 00001932 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2491 00001935 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2492 00001937 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2493                              <1> OK_FUNC:
  2494 00001939 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2495 0000193C 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2496 0000193E 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2497 00001941 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2498 00001943 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2499 00001946 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2500 00001948 B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2501                              <1> OK_DRV:
  2502 0000194A 31C9                <1> 	xor	ecx, ecx
  2503                              <1> 	;mov	esi, ecx ; 08/02/2015
  2504                              <1> 	; 05/12/2021
  2505 0000194C 89CE                <1> 	mov	esi, ecx
  2506 0000194E 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2507 00001950 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2508                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2509                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2510 00001952 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2511 00001955 BB[8D190000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2512 0000195A 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2513 0000195C 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2514 0000195E 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2515 00001960 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2516 00001963 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2517                              <1> 	;
  2518                              <1> 	; 11/12/2014
  2519 00001966 8815[216B0000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2520                              <1> 	;
  2521 0000196C 8A25[BC700000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2522 00001972 C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2523                              <1> 
  2524                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2525                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2526                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2527                              <1> ;
  2528                              <1> ;		DI	: DRIVE #
  2529                              <1> ;		SI-HI	: HEAD #
  2530                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2531                              <1> ;		ES	: BUFFER SEGMENT
  2532                              <1> ;		[BP]	: SECTOR #
  2533                              <1> ;		[BP+1]	: TRACK #
  2534                              <1> ;		[BP+2]	: BUFFER OFFSET
  2535                              <1> ;
  2536                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2537                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2538                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2539                              <1> ;	SPECIFIC ERROR CODE.
  2540                              <1> ;
  2541                              <1> 					; (AH) = @DSKETTE_STATUS
  2542 00001979 FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2543 0000197B 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2544 0000197C 1F                  <1> 	POP	DS
  2545 0000197D 07                  <1> 	pop	es	; 06/02/2015
  2546 0000197E 59                  <1> 	POP	eCX
  2547 0000197F 5B                  <1> 	POP	eBX
  2548 00001980 5A                  <1> 	POP	eDX
  2549 00001981 5F                  <1> 	POP	eDI
  2550 00001982 89E5                <1> 	MOV	eBP, eSP
  2551 00001984 50                  <1> 	PUSH	eAX
  2552 00001985 9C                  <1> 	PUSHFd
  2553 00001986 58                  <1> 	POP	eAX
  2554                              <1> 	;MOV	[BP+6], AX
  2555 00001987 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2556 0000198A 58                  <1> 	POP	eAX
  2557 0000198B 5D                  <1> 	POP	eBP
  2558 0000198C CF                  <1> 	IRETd
  2559                              <1> 
  2560                              <1> ;-------------------------------------------------------------------------------
  2561                              <1> ; DW --> dd (06/02/2015)
  2562 0000198D [F1190000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2563 00001991 [661A0000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2564 00001995 [761A0000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2565 00001999 [871A0000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2566 0000199D [981A0000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2567 000019A1 [A91A0000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2568 000019A5 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2569 000019A9 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2570 000019AD [391B0000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2571 000019B1 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2572 000019B5 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2573 000019B9 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2574 000019BD [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2575 000019C1 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2576 000019C5 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2577 000019C9 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2578 000019CD [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2579 000019D1 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2580 000019D5 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2581 000019D9 [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2582 000019DD [2D1B0000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2583 000019E1 [F81B0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2584 000019E5 [201C0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2585 000019E9 [591C0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2586 000019ED [DA1C0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2587                              <1> FNC_TAE EQU     $                       ; END
  2588                              <1> 
  2589                              <1> ;-------------------------------------------------------------------------------
  2590                              <1> ; DISK_RESET	(AH = 00H)	
  2591                              <1> ;		RESET THE DISKETTE SYSTEM.
  2592                              <1> ;
  2593                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2594                              <1> ;-------------------------------------------------------------------------------
  2595                              <1> DSK_RESET:
  2596 000019F1 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2597 000019F5 FA                  <1> 	CLI				; NO INTERRUPTS
  2598 000019F6 A0[BA700000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2599 000019FB 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2600 000019FD C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2601                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2602 00001A00 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2603 00001A02 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2604 00001A03 C605[B9700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2605                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2606                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2607                              <1> 					;      PULSE WIDTH)
  2608                              <1> 	; 19/12/2014
  2609                              <1> 	NEWIODELAY
  2082 00001A0A E6EB                <2>  out 0EBh,al
  2610                              <1> 
  2611                              <1> 	; 17/12/2014 
  2612                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2613 00001A0C B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2614                              <1> wdw1:
  2615                              <1> 	NEWIODELAY   ; 27/02/2015
  2082 00001A11 E6EB                <2>  out 0EBh,al
  2616 00001A13 E2FC                <1> 	loop	wdw1
  2617                              <1> 	;
  2618 00001A15 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2619 00001A17 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2620                              <1> 	; 16/12/2014
  2621                              <1> 	IODELAY
  2077 00001A18 EB00                <2>  jmp short $+2
  2078 00001A1A EB00                <2>  jmp short $+2
  2622                              <1> 	;
  2623                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2624 00001A1C E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2625 00001A21 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2626 00001A23 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2627                              <1> NXT_DRV:
  2628                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2629                              <1> 	; 05/12/2021
  2630 00001A27 51                  <1> 	push	ecx
  2631 00001A28 B8[5C1A0000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2632 00001A2D 50                  <1> 	PUSH	eAX			; "
  2633 00001A2E B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2634 00001A30 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2635 00001A35 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2636 00001A36 E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2637                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2638                              <1> 	; 05/12/2021
  2639 00001A3B 59                  <1> 	pop	ecx
  2640 00001A3C 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2641 00001A3E 3A0D[BD700000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2642 00001A44 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2643 00001A46 FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2644 00001A48 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2645 00001A4B 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2646                              <1> 	;
  2647 00001A4D E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2648                              <1> RESBAC:
  2649 00001A52 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2650                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2651                              <1> 	; 05/12/2021
  2652 00001A57 89F3                <1> 	mov	ebx, esi
  2653 00001A59 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2654 00001A5B C3                  <1> 	RETn		
  2655                              <1> DR_POP_ERR:
  2656                              <1> 	;POP	CX			; CLEAR STACK
  2657                              <1> 	; 05/12/2021
  2658 00001A5C 59                  <1> 	pop	ecx
  2659                              <1> DR_ERR:
  2660 00001A5D 800D[BC700000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2661 00001A64 EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2662                              <1> 
  2663                              <1> ;-------------------------------------------------------------------------------
  2664                              <1> ; DISK_STATUS	(AH = 01H)
  2665                              <1> ;	DISKETTE STATUS.
  2666                              <1> ;
  2667                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2668                              <1> ;
  2669                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2670                              <1> ;-------------------------------------------------------------------------------
  2671                              <1> DSK_STATUS:
  2672 00001A66 8825[BC700000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2673 00001A6C E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2674                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2675                              <1> 	; 05/12/2021
  2676 00001A71 89F3                <1> 	mov	ebx, esi
  2677 00001A73 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2678 00001A75 C3                  <1> 	RETn		
  2679                              <1> 
  2680                              <1> ;-------------------------------------------------------------------------------
  2681                              <1> ; DISK_READ	(AH = 02H)	
  2682                              <1> ;	DISKETTE READ.
  2683                              <1> ;
  2684                              <1> ; ON ENTRY:	DI	: DRIVE #
  2685                              <1> ;		SI-HI	: HEAD #
  2686                              <1> ;		SI-LOW	: # OF SECTORS
  2687                              <1> ;		ES	: BUFFER SEGMENT
  2688                              <1> ;		[BP]	: SECTOR #
  2689                              <1> ;		[BP+1]	: TRACK #
  2690                              <1> ;		[BP+2]	: BUFFER OFFSET
  2691                              <1> ;
  2692                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2693                              <1> ;-------------------------------------------------------------------------------
  2694                              <1> 
  2695                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2696                              <1> 
  2697                              <1> DSK_READ:
  2698 00001A76 8025[BA700000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2699 00001A7D 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2700 00001A81 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2701 00001A86 C3                  <1> 	RETn
  2702                              <1> 
  2703                              <1> ;-------------------------------------------------------------------------------
  2704                              <1> ; DISK_WRITE	(AH = 03H)
  2705                              <1> ;	DISKETTE WRITE.
  2706                              <1> ;
  2707                              <1> ; ON ENTRY:	DI	: DRIVE #
  2708                              <1> ;		SI-HI	: HEAD #
  2709                              <1> ;		SI-LOW	: # OF SECTORS
  2710                              <1> ;		ES	: BUFFER SEGMENT
  2711                              <1> ;		[BP]	: SECTOR #
  2712                              <1> ;		[BP+1]	: TRACK #
  2713                              <1> ;		[BP+2]	: BUFFER OFFSET
  2714                              <1> ;
  2715                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2716                              <1> ;-------------------------------------------------------------------------------
  2717                              <1> 
  2718                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2719                              <1> 
  2720                              <1> DSK_WRITE:
  2721 00001A87 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2722 00001A8B 800D[BA700000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2723 00001A92 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2724 00001A97 C3                  <1> 	RETn
  2725                              <1> 
  2726                              <1> ;-------------------------------------------------------------------------------
  2727                              <1> ; DISK_VERF	(AH = 04H)
  2728                              <1> ;	DISKETTE VERIFY.
  2729                              <1> ;
  2730                              <1> ; ON ENTRY:	DI	: DRIVE #
  2731                              <1> ;		SI-HI	: HEAD #
  2732                              <1> ;		SI-LOW	: # OF SECTORS
  2733                              <1> ;		ES	: BUFFER SEGMENT
  2734                              <1> ;		[BP]	: SECTOR #
  2735                              <1> ;		[BP+1]	: TRACK #
  2736                              <1> ;		[BP+2]	: BUFFER OFFSET
  2737                              <1> ;
  2738                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2739                              <1> ;-------------------------------------------------------------------------------
  2740                              <1> DSK_VERF:
  2741 00001A98 8025[BA700000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2742 00001A9F 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2743 00001AA3 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2744 00001AA8 C3                  <1> 	RETn
  2745                              <1> 
  2746                              <1> ;-------------------------------------------------------------------------------
  2747                              <1> ; DISK_FORMAT	(AH = 05H)
  2748                              <1> ;	DISKETTE FORMAT.
  2749                              <1> ;
  2750                              <1> ; ON ENTRY:	DI	: DRIVE #
  2751                              <1> ;		SI-HI	: HEAD #
  2752                              <1> ;		SI-LOW	: # OF SECTORS
  2753                              <1> ;		ES	: BUFFER SEGMENT
  2754                              <1> ;		[BP]	: SECTOR #
  2755                              <1> ;		[BP+1]	: TRACK #
  2756                              <1> ;		[BP+2]	: BUFFER OFFSET
  2757                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2758                              <1> ;
  2759                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2760                              <1> ;-------------------------------------------------------------------------------
  2761                              <1> DSK_FORMAT:
  2762 00001AA9 E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2763 00001AAE E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2764 00001AB3 800D[BA700000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2765 00001ABA E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2766 00001ABF 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2767 00001AC1 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2768 00001AC6 E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2769 00001ACB 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2770 00001ACD E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2771                              <1> FM_WR:
  2772 00001AD2 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2773 00001AD7 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2774 00001AD9 B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2775 00001ADB E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2776 00001AE0 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2777 00001AE2 B8[1E1B0000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2778 00001AE7 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2779 00001AE8 B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2780 00001AEA E80E090000          <1> 	CALL	GET_PARM
  2781 00001AEF E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2782 00001AF4 B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2783 00001AF6 E802090000          <1> 	CALL	GET_PARM
  2784 00001AFB E8030A0000          <1> 	CALL	NEC_OUTPUT
  2785 00001B00 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2786 00001B02 E8F6080000          <1> 	CALL	GET_PARM
  2787 00001B07 E8F7090000          <1> 	CALL	NEC_OUTPUT
  2788 00001B0C B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2789 00001B0E E8EA080000          <1> 	CALL	GET_PARM
  2790 00001B13 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2791 00001B18 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2792 00001B19 E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2793                              <1> FM_DON:
  2794 00001B1E E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2795 00001B23 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2796                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2797 00001B28 89F3                <1> 	mov	ebx, esi ; 05/12/2021
  2798 00001B2A 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2799 00001B2C C3                  <1> 	RETn
  2800                              <1> 
  2801                              <1> ;-------------------------------------------------------------------------------
  2802                              <1> ; FNC_ERR
  2803                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2804                              <1> ;	SET BAD COMMAND IN STATUS.
  2805                              <1> ;
  2806                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2807                              <1> ;-------------------------------------------------------------------------------
  2808                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2809                              <1> 	;MOV	AX,SI			; RESTORE AL
  2810                              <1> 	; 05/12/2021
  2811 00001B2D 89F0                <1> 	mov	eax, esi
  2812 00001B2F B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2813 00001B31 8825[BC700000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2814 00001B37 F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2815 00001B38 C3                  <1> 	RETn
  2816                              <1> 
  2817                              <1> ;-------------------------------------------------------------------------------
  2818                              <1> ; DISK_PARMS	(AH = 08H)	
  2819                              <1> ;	READ DRIVE PARAMETERS.
  2820                              <1> ;
  2821                              <1> ; ON ENTRY:	DI : DRIVE #
  2822                              <1> ;
  2823                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2824                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2825                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2826                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2827                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2828                              <1> ;		BH/[BP+3] = 0
  2829                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2830                              <1> ;		DH/[BP+5] = MAX HEAD #
  2831                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2832                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2833                              <1> ;		AX        = 0
  2834                              <1> ;
  2835                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2836                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2837                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2838                              <1> ;		       CALLER.
  2839                              <1> ;-------------------------------------------------------------------------------
  2840                              <1> DSK_PARMS:
  2841 00001B39 E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2842                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2843 00001B3E 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2844 00001B40 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2845                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2846                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2847                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2848                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2849                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2850                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2851                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2852                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2853                              <1> 	;sub	edx, edx
  2854 00001B43 66A1[2E6B0000]      <1> 	mov     ax, [fd0_type]
  2855 00001B49 6621C0              <1> 	and     ax, ax
  2856 00001B4C 7473                <1> 	jz      short NON_DRV
  2857 00001B4E FEC2                <1> 	inc     dl
  2858 00001B50 20E4                <1> 	and     ah, ah
  2859 00001B52 7402                <1> 	jz      short STO_DL
  2860 00001B54 FEC2                <1> 	inc     dl
  2861                              <1> STO_DL:
  2862                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2863 00001B56 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2864 00001B59 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2865 00001B5D 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2866                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2867 00001B5F C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2868 00001B63 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2869                              <1> 	;;20/02/2015
  2870                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2871                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2872 00001B68 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2873 00001B6A E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2874 00001B6F 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2875                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2876 00001B71 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2877 00001B74 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2878 00001B77 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2879 00001B7A EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2880                              <1> CHK_EST:
  2881 00001B7C 8AA7[C9700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2882 00001B82 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2883 00001B85 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2884                              <1> USE_EST:
  2885 00001B87 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2886 00001B8A 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2887 00001B8D 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2888                              <1> 
  2889                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2890                              <1> 
  2891 00001B8F B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2892 00001B91 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2893 00001B96 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2894 00001B99 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2895 00001B9C F687[C9700000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2896 00001BA3 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2897                              <1> 
  2898                              <1> ;-----	IT IS 1.44 MB DRIVE
  2899                              <1> 
  2900                              <1> PARM144:
  2901 00001BA5 B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2902 00001BA7 E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2903 00001BAC 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2904 00001BAF 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2905                              <1> STO_CX:
  2906 00001BB2 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2907                              <1> ES_DI:
  2908                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2909 00001BB5 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2910                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2911                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2912                              <1> DP_OUT:
  2913 00001BB8 E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2914                              <1> 	;XOR	AX,AX			; CLEAR
  2915                              <1> 	; 05/12/2021
  2916 00001BBD 31C0                <1> 	xor	eax, eax
  2917 00001BBF F8                  <1> 	CLC
  2918 00001BC0 C3                  <1> 	RETn
  2919                              <1> 
  2920                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2921                              <1> 
  2922                              <1> NON_DRV:
  2923                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2924 00001BC1 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2925                              <1> NON_DRV1:
  2926 00001BC4 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2927 00001BC9 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  2928                              <1> 
  2929                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  2930                              <1> 	
  2931 00001BCB E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  2932                              <1> 	;MOV	AX,SI			; RESTORE AL
  2933 00001BD0 89F0                <1> 	mov	eax, esi ; 05/12/2021
  2934 00001BD2 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2935 00001BD4 F9                  <1> 	STC
  2936 00001BD5 C3                  <1> 	RETn
  2937                              <1> 
  2938                              <1> NON_DRV2:
  2939                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  2940 00001BD6 31C0                <1> 	xor	eax, eax	
  2941 00001BD8 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  2942                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  2943 00001BDC 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  2944                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  2945 00001BDF 89450C              <1> 	mov	[ebp+12], eax
  2946                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2947 00001BE2 EBD4                <1> 	JMP	SHORT DP_OUT
  2948                              <1> 
  2949                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  2950                              <1> 
  2951                              <1> USE_EST2:
  2952 00001BE4 B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  2953 00001BE6 E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2954 00001BEB 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2955 00001BEE 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2956 00001BF1 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  2957 00001BF4 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  2958 00001BF6 EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  2959                              <1> 
  2960                              <1> ;-------------------------------------------------------------------------------
  2961                              <1> ; DISK_TYPE (AH = 15H)	
  2962                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  2963                              <1> ;
  2964                              <1> ;  ON ENTRY:	DI = DRIVE #
  2965                              <1> ;
  2966                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  2967                              <1> ;-------------------------------------------------------------------------------
  2968                              <1> DSK_TYPE:
  2969 00001BF8 E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2970 00001BFD 8A87[C9700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  2971 00001C03 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  2972 00001C05 7415                <1> 	JZ	short NO_DRV
  2973 00001C07 B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  2974 00001C09 A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  2975 00001C0B 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  2976 00001C0D B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  2977                              <1> DT_BACK:
  2978                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  2979 00001C0F 50                  <1> 	push	eax ; 05/12/2021
  2980 00001C10 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2981                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  2982 00001C15 58                  <1> 	pop	eax ; 05/12/2021
  2983 00001C16 F8                  <1> 	CLC				; NO ERROR
  2984                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2985                              <1> 	; 05/12/2021
  2986 00001C17 89F3                <1> 	mov	ebx, esi
  2987 00001C19 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2988 00001C1B C3                  <1> 	RETn
  2989                              <1> NO_DRV:	
  2990 00001C1C 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  2991 00001C1E EBEF                <1> 	JMP	SHORT DT_BACK
  2992                              <1> 
  2993                              <1> ;-------------------------------------------------------------------------------
  2994                              <1> ; DISK_CHANGE	(AH = 16H)
  2995                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  2996                              <1> ;
  2997                              <1> ; ON ENTRY:	DI = DRIVE #
  2998                              <1> ;
  2999                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3000                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3001                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3002                              <1> ;-------------------------------------------------------------------------------
  3003                              <1> DSK_CHANGE:
  3004 00001C20 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3005 00001C25 8A87[C9700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3006 00001C2B 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3007 00001C2D 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3008 00001C2F A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3009 00001C31 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3010                              <1> DC0:
  3011 00001C33 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3012 00001C38 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3013                              <1> 
  3014 00001C3A C605[BC700000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3015                              <1> 
  3016 00001C41 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3017 00001C46 E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3018                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3019                              <1> 	; 05/12/2021
  3020 00001C4B 89F3                <1> 	mov	ebx, esi
  3021 00001C4D 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3022 00001C4F C3                  <1> 	RETn
  3023                              <1> DC_NON:
  3024 00001C50 800D[BC700000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3025 00001C57 EBE8                <1> 	JMP	SHORT FINIS
  3026                              <1> 
  3027                              <1> ;-------------------------------------------------------------------------------
  3028                              <1> ; FORMAT_SET	(AH = 17H)
  3029                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3030                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3031                              <1> ;
  3032                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3033                              <1> ;		DI     = DRIVE #
  3034                              <1> ;
  3035                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3036                              <1> ;		AH = @DSKETTE_STATUS
  3037                              <1> ;		CY = 1 IF ERROR
  3038                              <1> ;-------------------------------------------------------------------------------
  3039                              <1> FORMAT_SET:
  3040 00001C59 E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3041                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3042                              <1> 	; 05/12/2021
  3043 00001C5E 56                  <1> 	push	esi
  3044 00001C5F 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3045 00001C62 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3046 00001C64 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3047 00001C67 80A7[C9700000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3048 00001C6E 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3049 00001C70 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3050 00001C72 808F[C9700000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3051 00001C79 EB48                <1> 	JMP	SHORT S0
  3052                              <1> NOT_320:
  3053 00001C7B E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3054 00001C80 803D[BC700000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3055 00001C87 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3056                              <1> S3:
  3057 00001C89 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3058 00001C8B 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3059 00001C8D 808F[C9700000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3060 00001C94 EB2D                <1> 	JMP	SHORT S0
  3061                              <1> NOT_320_12:
  3062 00001C96 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3063 00001C98 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3064 00001C9A 808F[C9700000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3065 00001CA1 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3066                              <1> NOT_12:	
  3067 00001CA3 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3068 00001CA5 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3069                              <1> 
  3070 00001CA7 F687[C9700000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3071 00001CAE 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3072 00001CB0 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3073 00001CB2 F687[C9700000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3074 00001CB9 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3075                              <1> ASSUME:
  3076 00001CBB B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3077                              <1> OR_IT_IN:
  3078 00001CBD 0887[C9700000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3079                              <1> S0:
  3080 00001CC3 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3081 00001CC8 E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3082                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3083                              <1> 	; 05/12/2021
  3084 00001CCD 5B                  <1> 	pop	ebx
  3085 00001CCE 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3086 00001CD0 C3                  <1> 	RETn
  3087                              <1> FS_ERR:
  3088 00001CD1 C605[BC700000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3089 00001CD8 EBE9                <1> 	JMP	SHORT S0
  3090                              <1> 
  3091                              <1> ;-------------------------------------------------------------------------------
  3092                              <1> ; SET_MEDIA	(AH = 18H)
  3093                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3094                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3095                              <1> ;
  3096                              <1> ; ON ENTRY:
  3097                              <1> ;	[BP]	= SECTOR PER TRACK
  3098                              <1> ;	[BP+1]	= TRACK #
  3099                              <1> ;	DI	= DRIVE #
  3100                              <1> ;
  3101                              <1> ; ON EXIT:
  3102                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3103                              <1> ;	IF NO ERROR:
  3104                              <1> ;		AH = 0
  3105                              <1> ;		CY = 0
  3106                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3107                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3108                              <1> ;	IF ERROR:	
  3109                              <1> ;		AH = @DSKETTE_STATUS
  3110                              <1> ;		CY = 1
  3111                              <1> ;-------------------------------------------------------------------------------
  3112                              <1> SET_MEDIA:
  3113 00001CDA E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3114 00001CDF F687[C9700000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3115 00001CE6 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3116 00001CE8 E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3117 00001CED 803D[BC700000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3118 00001CF4 746B                <1> 	JE	short SM_RTN
  3119 00001CF6 C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3120                              <1> SM_CMOS:
  3121 00001CFD E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3122                              <1> 	;;20/02/2015
  3123                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3124                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3125 00001D02 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3126 00001D04 E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3127 00001D09 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3128 00001D0B 57                  <1> 	PUSH	eDI			; SAVE REG.
  3129 00001D0C 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3130 00001D0E B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3131                              <1> DR_SEARCH:
  3132 00001D13 8AA3[AC6A0000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3133 00001D19 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3134 00001D1C 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3135 00001D1E 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3136                              <1> DR_FND:
  3137 00001D20 8BBB[AD6A0000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3138                              <1> MD_SEARCH:
  3139 00001D26 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3140 00001D29 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3141 00001D2C 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3142 00001D2E 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3143 00001D31 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3144 00001D34 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3145                              <1> NXT_MD:
  3146                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3147 00001D36 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3148 00001D39 E2D8                <1> 	LOOP    DR_SEARCH
  3149 00001D3B 5F                  <1> 	POP	eDI			; RESTORE REG.
  3150                              <1> MD_NOT_FND:
  3151 00001D3C C605[BC700000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3152 00001D43 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3153                              <1> MD_FND:
  3154 00001D45 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3155 00001D48 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3156 00001D4A 7502                <1> 	JNE	short MD_SET
  3157 00001D4C 0C20                <1> 	OR	AL,DBL_STEP
  3158                              <1> MD_SET:
  3159                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3160 00001D4E 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3161 00001D51 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3162 00001D53 5F                  <1> 	POP	eDI
  3163 00001D54 80A7[C9700000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3164 00001D5B 0887[C9700000]      <1> 	OR	[DSK_STATE+eDI], AL
  3165                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3166                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3167                              <1> SM_RTN:
  3168 00001D61 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3169 00001D66 E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3170 00001D6B C3                  <1> 	RETn
  3171                              <1> 
  3172                              <1> ;----------------------------------------------------------------
  3173                              <1> ; DR_TYPE_CHECK							:
  3174                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3175                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3176                              <1> ; ON ENTRY:							:
  3177                              <1> ;	AL = DRIVE TYPE						:
  3178                              <1> ; ON EXIT:							:
  3179                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3180                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3181                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3182                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3183                              <1> ; REGISTERS ALTERED: eBX						:
  3184                              <1> ;----------------------------------------------------------------		
  3185                              <1> DR_TYPE_CHECK:
  3186                              <1> 	;PUSH	AX			
  3187                              <1> 	; 05/12/2021
  3188 00001D6C 50                  <1> 	push	eax
  3189 00001D6D 51                  <1> 	PUSH	eCX
  3190 00001D6E 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3191 00001D70 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3192                              <1> TYPE_CHK:	
  3193 00001D75 8AA3[AC6A0000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3194 00001D7B 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3195 00001D7D 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3196                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3197 00001D7F 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3198 00001D82 E2F1                <1> 	LOOP    TYPE_CHK
  3199                              <1> 	;
  3200 00001D84 BB[0B6B0000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3201                              <1> 					; Default for GET_PARM (11/12/2014)
  3202                              <1> 	;
  3203 00001D89 F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3204 00001D8A EB06                <1> 	JMP	SHORT TYPE_RTN
  3205                              <1> DR_TYPE_VALID:
  3206 00001D8C 8B9B[AD6A0000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3207                              <1> TYPE_RTN:
  3208 00001D92 59                  <1> 	POP	eCX
  3209                              <1> 	;POP	AX
  3210                              <1> 	; 05/12/2021
  3211 00001D93 58                  <1> 	pop	eax
  3212 00001D94 C3                  <1> 	RETn	
  3213                              <1> 		
  3214                              <1> ;----------------------------------------------------------------
  3215                              <1> ; SEND_SPEC							:
  3216                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3217                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3218                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3219                              <1> ; ON EXIT:	NONE						:	
  3220                              <1> ; REGISTERS ALTERED: CX, DX					:
  3221                              <1> ;----------------------------------------------------------------		
  3222                              <1> SEND_SPEC:
  3223 00001D95 50                  <1> 	PUSH	eAX			; SAVE AX
  3224 00001D96 B8[BC1D0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3225 00001D9B 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3226 00001D9C B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3227 00001D9E E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3228 00001DA3 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3229 00001DA5 E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3230 00001DAA E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3231 00001DAF B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3232 00001DB1 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3233 00001DB6 E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3234 00001DBB 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3235                              <1> SPECBAC:
  3236 00001DBC 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3237 00001DBD C3                  <1> 	RETn
  3238                              <1> 
  3239                              <1> ;----------------------------------------------------------------
  3240                              <1> ; SEND_SPEC_MD							:
  3241                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3242                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3243                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3244                              <1> ; ON EXIT:	NONE						:	
  3245                              <1> ; REGISTERS ALTERED: AX						:
  3246                              <1> ;----------------------------------------------------------------		
  3247                              <1> SEND_SPEC_MD:
  3248 00001DBE 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3249 00001DBF B8[DC1D0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3250 00001DC4 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3251 00001DC5 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3252 00001DC7 E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3253 00001DCC 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3254 00001DCE E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3255 00001DD3 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3256 00001DD6 E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3257 00001DDB 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3258                              <1> SPEC_ESBAC:
  3259 00001DDC 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3260 00001DDD C3                  <1> 	RETn
  3261                              <1> 
  3262                              <1> ;-------------------------------------------------------------------------------
  3263                              <1> ; XLAT_NEW  
  3264                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3265                              <1> ;	MODE TO NEW ARCHITECTURE.
  3266                              <1> ;
  3267                              <1> ; ON ENTRY:	DI = DRIVE #
  3268                              <1> ;-------------------------------------------------------------------------------
  3269                              <1> XLAT_NEW:
  3270 00001DDE 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3271 00001DE1 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3272 00001DE3 80BF[C9700000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3273 00001DEA 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3274 00001DEC 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3275 00001DEF C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3276 00001DF2 A0[C8700000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3277 00001DF7 D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3278 00001DF9 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3279 00001DFB 80A7[C9700000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3280 00001E02 0887[C9700000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3281                              <1> XN_OUT:
  3282 00001E08 C3                  <1> 	RETn
  3283                              <1> DO_DET:
  3284 00001E09 E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3285 00001E0E C3                  <1> 	RETn
  3286                              <1> 
  3287                              <1> ;-------------------------------------------------------------------------------
  3288                              <1> ; XLAT_OLD 
  3289                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3290                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3291                              <1> ;
  3292                              <1> ; ON ENTRY:	DI = DRIVE
  3293                              <1> ;-------------------------------------------------------------------------------
  3294                              <1> XLAT_OLD:
  3295 00001E0F 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3296                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3297                              <1>         ;ja	XO_OUT
  3298                              <1>         ; 05/12/2021
  3299 00001E12 77F4                <1> 	ja	short XN_OUT
  3300 00001E14 80BF[C9700000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3301 00001E1B 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3302                              <1> 
  3303                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3304                              <1> 
  3305 00001E1D 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3306 00001E20 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3307 00001E23 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3308 00001E25 D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3309 00001E27 8425[C8700000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3310 00001E2D 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3311                              <1> 
  3312                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3313                              <1> 
  3314 00001E2F B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3315 00001E31 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3316 00001E33 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3317 00001E35 2025[C8700000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3318                              <1> 
  3319                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3320                              <1> 
  3321 00001E3B 8A87[C9700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3322 00001E41 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3323 00001E43 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3324 00001E45 0805[C8700000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3325                              <1> 
  3326                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3327                              <1> 
  3328                              <1> SAVE_SET:
  3329 00001E4B 8AA7[C9700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3330 00001E51 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3331 00001E53 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3332 00001E56 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3333 00001E59 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3334 00001E5B B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3335 00001E5D 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3336 00001E60 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3337 00001E62 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3338 00001E65 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3339                              <1> UNKNO:
  3340 00001E67 B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3341 00001E69 EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3342                              <1> CHK_144:
  3343 00001E6B E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3344                              <1> 	;;20/02/2015
  3345                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3346 00001E70 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3347 00001E72 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3348 00001E74 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3349 00001E76 B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3350 00001E78 EB0C                <1> 	JMP	SHORT TST_DET
  3351                              <1> CHK_250:
  3352 00001E7A B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3353 00001E7C 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3354 00001E7F 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3355 00001E81 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3356 00001E84 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3357                              <1> TST_DET:
  3358 00001E86 F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3359 00001E89 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3360 00001E8B 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3361                              <1> AL_SET:
  3362 00001E8D 80A7[C9700000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3363 00001E94 0887[C9700000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3364                              <1> XO_OUT:
  3365 00001E9A C3                  <1> 	RETn
  3366                              <1> 
  3367                              <1> ;-------------------------------------------------------------------------------
  3368                              <1> ; RD_WR_VF
  3369                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3370                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3371                              <1> ;
  3372                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3373                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3374                              <1> ;
  3375                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3376                              <1> ;-------------------------------------------------------------------------------
  3377                              <1> RD_WR_VF:
  3378                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3379 00001E9B 50                  <1> 	push	eax ; 05/12/2021
  3380 00001E9C E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3381 00001EA1 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3382                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3383 00001EA6 58                  <1> 	pop	eax ; 05/12/2021
  3384                              <1> DO_AGAIN:
  3385                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3386 00001EA7 50                  <1> 	push	eax ; 05/12/2021
  3387 00001EA8 E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3388                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3389 00001EAD 58                  <1> 	pop	eax ; 05/12/2021
  3390                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3391                              <1> 	; 05/12/2021
  3392 00001EAE 7305                <1> 	jnc	short RWV
  3393 00001EB0 E9C3000000          <1> 	jmp	RWV_END
  3394                              <1> RWV:
  3395                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3396 00001EB5 50                  <1> 	push	eax ; 05/12/2021
  3397 00001EB6 8AB7[C9700000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3398 00001EBC 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3399 00001EBF E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3400                              <1> 	;;20/02/2015
  3401                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3402 00001EC4 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3403 00001EC6 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3404 00001EC8 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3405 00001ECA F687[C9700000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3406 00001ED1 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3407 00001ED3 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3408 00001ED5 EB0F                <1> 	JMP	SHORT RWV_2
  3409                              <1> RWV_1:
  3410 00001ED7 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3411 00001ED9 F687[C9700000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3412 00001EE0 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3413 00001EE2 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3414 00001EE4 EB04                <1> 	jmp	short rwv_3
  3415                              <1> RWV_2:
  3416 00001EE6 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3417 00001EE8 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3418                              <1> rwv_3:
  3419 00001EEA E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3420 00001EEF 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3421                              <1> 
  3422                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3423                              <1> 
  3424 00001EF1 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3425 00001EF2 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3426 00001EF4 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3427                              <1> RWV_DR_SEARCH:
  3428 00001EF9 8AA3[AC6A0000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3429 00001EFF 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3430 00001F02 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3431 00001F04 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3432                              <1> RWV_DR_FND:
  3433 00001F06 8BBB[AD6A0000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3434                              <1> RWV_MD_SEARH:
  3435 00001F0C 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3436 00001F0F 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3437                              <1> RWV_NXT_MD:
  3438                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3439 00001F11 83C305              <1> 	add	eBX, 5
  3440 00001F14 E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3441 00001F16 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3442                              <1> 
  3443                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3444                              <1> 
  3445                              <1> RWV_ASSUME:
  3446 00001F17 BB[CA6A0000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3447 00001F1C F687[C9700000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3448 00001F23 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3449 00001F25 BB[E46A0000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3450 00001F2A EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3451                              <1> 
  3452                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3453                              <1> 	 			
  3454                              <1> RWV_MD_FND:
  3455 00001F2C 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3456 00001F2E 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3457                              <1> 	
  3458                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3459                              <1> 
  3460                              <1> RWV_MD_FND1:
  3461 00001F2F E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3462 00001F34 E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3463 00001F39 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3464 00001F3B E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3465                              <1> RWV_DBL:
  3466 00001F40 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3467 00001F41 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3468 00001F46 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3469 00001F47 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3470                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3471 00001F49 58                  <1> 	pop	eax ; 05/12/2021
  3472                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3473 00001F4A 50                  <1> 	push	eax ; 05/12/2021
  3474 00001F4B 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3475 00001F4C E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3476 00001F51 5B                  <1> 	POP	eBX 
  3477                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3478 00001F52 58                  <1> 	pop	eax ; 05/12/2021
  3479 00001F53 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3480                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3481 00001F55 50                  <1> 	push	eax ; 05/12/2021
  3482 00001F56 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3483 00001F57 E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3484 00001F5C 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3485 00001F5D 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3486 00001F5F E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3487 00001F64 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3488 00001F66 E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3489                              <1> CHK_RET:
  3490 00001F6B E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3491                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3492 00001F70 58                  <1> 	pop	eax ; 05/12/2021
  3493 00001F71 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3494 00001F73 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3495                              <1> RWV_END:
  3496 00001F78 E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3497 00001F7D E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3498                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3499                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3500 00001F82 50                  <1> 	push	eax ; 05/12/2021
  3501 00001F83 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3502                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3503 00001F88 58                  <1> 	pop	eax ; 05/12/2021
  3504 00001F89 E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3505 00001F8E C3                  <1> 	RETn
  3506                              <1> 
  3507                              <1> ;-------------------------------------------------------------------------------
  3508                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3509                              <1> ;-------------------------------------------------------------------------------
  3510                              <1> SETUP_STATE:
  3511 00001F8F F687[C9700000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3512 00001F96 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3513 00001F98 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3514 00001F9C F687[C9700000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3515 00001FA3 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3516 00001FA5 F687[C9700000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3517 00001FAC 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3518 00001FAE 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3519                              <1> AX_SET:	
  3520 00001FB2 80A7[C9700000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3521 00001FB9 08A7[C9700000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3522 00001FBF 8025[C4700000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3523 00001FC6 C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3524 00001FC9 0805[C4700000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3525                              <1> J1C:	
  3526 00001FCF C3                  <1> 	RETn
  3527                              <1> 
  3528                              <1> ;-------------------------------------------------------------------------------
  3529                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3530                              <1> ;-------------------------------------------------------------------------------
  3531                              <1> FMT_INIT:
  3532 00001FD0 F687[C9700000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3533 00001FD7 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3534 00001FD9 E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3535                              <1> 	;; 20/02/2015
  3536                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3537 00001FDE 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3538 00001FE0 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3539                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3540 00001FE2 8AA7[C9700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3541 00001FE8 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3542 00001FEB 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3543 00001FED 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3544 00001FEF 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3545 00001FF2 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3546                              <1> N_360:	
  3547 00001FF4 FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3548 00001FF6 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3549                              <1> F1_RATE:
  3550 00001FF8 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3551 00001FFB EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3552                              <1> N_12:	
  3553 00001FFD FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3554 00001FFF 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3555 00002001 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3556 00002004 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3557 00002006 F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3558 00002009 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3559 0000200B 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3560 0000200E EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3561                              <1> N_720:
  3562 00002010 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3563 00002012 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3564 00002014 EBE2                <1> 	JMP	SHORT F1_RATE
  3565                              <1> ISNT_12: 
  3566 00002016 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3567                              <1> 
  3568                              <1> SKP_STATE:
  3569 00002019 88A7[C9700000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3570                              <1> F1_OUT:
  3571 0000201F C3                  <1> 	RETn
  3572                              <1> CL_DRV:	
  3573 00002020 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3574 00002022 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3575                              <1> 
  3576                              <1> ;-------------------------------------------------------------------------------
  3577                              <1> ; MED_CHANGE	
  3578                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3579                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3580                              <1> ;
  3581                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3582                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3583                              <1> ;-------------------------------------------------------------------------------
  3584                              <1> MED_CHANGE:
  3585 00002024 E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3586 00002029 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3587 0000202B 80A7[C9700000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3588                              <1> 
  3589                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3590                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3591                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3592                              <1> 
  3593 00002032 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3594 00002035 B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3595 00002037 D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3596 00002039 F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3597 0000203B FA                  <1> 	CLI				; NO INTERRUPTS
  3598 0000203C 2005[BA700000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3599 00002042 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3600 00002043 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3601                              <1> 
  3602                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3603                              <1> 
  3604 00002048 E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3605 0000204D B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3606 0000204F E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3607 00002054 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3608 00002056 E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3609 0000205B C605[BC700000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3610                              <1> OK1:
  3611 00002062 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3612 00002067 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3613                              <1> OK4:
  3614 00002069 C605[BC700000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3615                              <1> OK2:		
  3616 00002070 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3617 00002071 C3                  <1> 	RETn
  3618                              <1> MC_OUT:
  3619 00002072 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3620 00002073 C3                  <1> 	RETn
  3621                              <1> 
  3622                              <1> ;-------------------------------------------------------------------------------
  3623                              <1> ; SEND_RATE
  3624                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3625                              <1> ; ON ENTRY:	DI = DRIVE #
  3626                              <1> ; ON EXIT:	NONE
  3627                              <1> ; REGISTERS ALTERED: DX
  3628                              <1> ;-------------------------------------------------------------------------------
  3629                              <1> SEND_RATE:
  3630                              <1> 	;PUSH	AX			; SAVE REG.
  3631                              <1> 	; 05/12/2021
  3632 00002074 50                  <1> 	push	eax
  3633 00002075 8025[C4700000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3634 0000207C 8A87[C9700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3635 00002082 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3636 00002084 0805[C4700000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3637 0000208A C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3638 0000208D 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3639 00002091 EE                  <1> 	OUT	DX,AL
  3640                              <1> 	;POP	AX			; RESTORE REG.
  3641                              <1> 	; 05/12/2021
  3642 00002092 58                  <1> 	pop	eax
  3643 00002093 C3                  <1> 	RETn
  3644                              <1> 
  3645                              <1> ;-------------------------------------------------------------------------------
  3646                              <1> ; CHK_LASTRATE
  3647                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3648                              <1> ; ON ENTRY:
  3649                              <1> ;	DI = DRIVE #
  3650                              <1> ; ON EXIT:
  3651                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3652                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3653                              <1> ; REGISTERS ALTERED: DX
  3654                              <1> ;-------------------------------------------------------------------------------
  3655                              <1> CHK_LASTRATE:
  3656                              <1> 	;PUSH	AX			; SAVE REG.
  3657                              <1> 	; 05/12/2021
  3658 00002094 50                  <1> 	push	eax
  3659 00002095 2225[C4700000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3660 0000209B 8A87[C9700000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3661 000020A1 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3662 000020A5 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3663                              <1> 					; ZF = 1 RATE IS THE SAME
  3664                              <1> 	;POP	AX			; RESTORE REG.
  3665                              <1> 	; 05/12/2021
  3666 000020A7 58                  <1> 	pop	eax
  3667 000020A8 C3                  <1> 	RETn
  3668                              <1> 
  3669                              <1> ;-------------------------------------------------------------------------------
  3670                              <1> ; DMA_SETUP
  3671                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3672                              <1> ;
  3673                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3674                              <1> ;
  3675                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3676                              <1> ;-------------------------------------------------------------------------------
  3677                              <1> 
  3678                              <1> ; SI = Head #, # of Sectors or DASD Type
  3679                              <1> 
  3680                              <1> ; 22/08/2015
  3681                              <1> ; 08/02/2015 - Protected Mode Modification
  3682                              <1> ; 06/02/2015 - 07/02/2015
  3683                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3684                              <1> ; (DMA Addres = Physical Address)
  3685                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3686                              <1> ;
  3687                              <1> ; 04/02/2016 (clc)
  3688                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3689                              <1> ; 16/12/2014 (IODELAY)
  3690                              <1> 
  3691                              <1> DMA_SETUP:
  3692                              <1> 
  3693                              <1> ;; 20/02/2015
  3694 000020A9 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3695 000020AC F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3696 000020B2 7569                <1> 	jnz	short dma_bnd_err_stc
  3697                              <1> 	;
  3698                              <1> 	;push	ax			; DMA command
  3699                              <1> 	; 05/12/2021
  3700 000020B4 50                  <1> 	push	eax
  3701 000020B5 52                  <1> 	push	edx			; *
  3702 000020B6 B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3703 000020B8 E840030000          <1> 	call	GET_PARM		; 
  3704 000020BD 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3705                              <1> 	;mov	ax, si			; Sector count
  3706                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3707                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3708                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3709                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3710                              <1> 	; 05/12/2021
  3711 000020BF 89F2                <1> 	mov	edx, esi
  3712 000020C1 29C0                <1> 	sub	eax, eax
  3713 000020C3 88D4                <1> 	mov	ah, dl
  3714 000020C5 D1E8                <1> 	shr	eax, 1
  3715 000020C7 D3E0                <1> 	shl	eax, cl
  3716                              <1> 	;
  3717 000020C9 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3718 000020CB 6689C1              <1> 	mov	cx, ax
  3719 000020CE 5A                  <1> 	pop	edx			; *
  3720                              <1> 	;pop	ax
  3721                              <1> 	; 05/12/2021
  3722 000020CF 58                  <1> 	pop	eax
  3723 000020D0 3C42                <1> 	cmp	al, 42h
  3724 000020D2 7507                <1>         jne     short NOT_VERF
  3725 000020D4 BA0000FF00          <1> 	mov	edx, 0FF0000h
  3726 000020D9 EB08                <1> 	jmp	short J33
  3727                              <1> NOT_VERF:
  3728 000020DB 6601CA              <1> 	add	dx, cx			; check for overflow
  3729 000020DE 723E                <1> 	jc	short dma_bnd_err
  3730                              <1> 	;
  3731 000020E0 6629CA              <1> 	sub	dx, cx			; Restore start address
  3732                              <1> J33:
  3733 000020E3 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3734 000020E4 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3735                              <1> 	IODELAY				; WAIT FOR I/O
  2077 000020E6 EB00                <2>  jmp short $+2
  2078 000020E8 EB00                <2>  jmp short $+2
  3736 000020EA E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3737 000020EC 89D0                <1> 	mov	eax,edx			; Buffer address
  3738 000020EE E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3739                              <1> 	IODELAY				; WAIT FOR I/O
  2077 000020F0 EB00                <2>  jmp short $+2
  2078 000020F2 EB00                <2>  jmp short $+2
  3740 000020F4 88E0                <1> 	MOV	AL,AH
  3741 000020F6 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3742 000020F8 C1E810              <1> 	shr	eax,16
  3743                              <1> 	IODELAY				; I/O WAIT STATE
  2077 000020FB EB00                <2>  jmp short $+2
  2078 000020FD EB00                <2>  jmp short $+2
  3744 000020FF E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3745                              <1> 	IODELAY
  2077 00002101 EB00                <2>  jmp short $+2
  2078 00002103 EB00                <2>  jmp short $+2
  3746 00002105 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3747 00002108 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3748                              <1> 	IODELAY				; WAIT FOR I/O
  2077 0000210A EB00                <2>  jmp short $+2
  2078 0000210C EB00                <2>  jmp short $+2
  3749 0000210E 88E0                <1> 	MOV	AL,AH
  3750 00002110 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3751                              <1> 	IODELAY
  2077 00002112 EB00                <2>  jmp short $+2
  2078 00002114 EB00                <2>  jmp short $+2
  3752 00002116 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3753 00002117 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3754 00002119 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3755                              <1> 
  3756 0000211B F8                  <1> 	clc	; 04/02/2016
  3757 0000211C C3                  <1> 	retn
  3758                              <1> 
  3759                              <1> dma_bnd_err_stc:
  3760 0000211D F9                  <1> 	stc
  3761                              <1> dma_bnd_err:
  3762 0000211E C605[BC700000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3763 00002125 C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3764                              <1> 
  3765                              <1> ;; 16/12/2014
  3766                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3767                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3768                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3769                              <1> ;;	IODELAY
  3770                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3771                              <1> ;;	;SIODELAY
  3772                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3773                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3774                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3775                              <1> ;;      ;JMP	SHORT J33
  3776                              <1> ;;;NOT_VERF:	
  3777                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3778                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3779                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3780                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3781                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3782                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3783                              <1> ;;	;JNC	short J33
  3784                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3785                              <1> ;;;J33:
  3786                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3787                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3788                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3789                              <1> ;;	IODELAY
  3790                              <1> ;;	MOV	AL,AH
  3791                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3792                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3793                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3794                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3795                              <1> ;;	IODELAY
  3796                              <1> ;;	;AND	AL,00001111B
  3797                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3798                              <1> ;;	;SIODELAY
  3799                              <1> ;;
  3800                              <1> ;;;----- DETERMINE COUNT
  3801                              <1> ;;	sub	eax, eax ; 08/02/2015
  3802                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3803                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3804                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3805                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3806                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3807                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3808                              <1> ;;	CALL	GET_PARM		; "
  3809                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3810                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3811                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3812                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3813                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3814                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3815                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3816                              <1> ;;	IODELAY
  3817                              <1> ;;	MOV	AL, AH
  3818                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3819                              <1> ;;	;IODELAY
  3820                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3821                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3822                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3823                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3824                              <1> ;;	add	ecx, eax ; 08/02/2015
  3825                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3826                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3827                              <1> ;;	SIODELAY
  3828                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3829                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3830                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3831                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3832                              <1> ;;	jz	short NO_BAD
  3833                              <1> ;;dma_bnd_err:
  3834                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3835                              <1> ;;NO_BAD:
  3836                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3837                              <1> 
  3838                              <1> ;-------------------------------------------------------------------------------
  3839                              <1> ; FMTDMA_SET
  3840                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3841                              <1> ;
  3842                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3843                              <1> ;
  3844                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3845                              <1> ;-------------------------------------------------------------------------------
  3846                              <1> 
  3847                              <1> 	; 05/12/2021
  3848                              <1> FMTDMA_SET:
  3849                              <1> ;; 20/02/2015 modification	
  3850 00002126 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3851 00002129 F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3852 0000212F 75EC                <1> 	jnz	short dma_bnd_err_stc
  3853                              <1> 	;
  3854                              <1> 	;push	dx			; *
  3855                              <1> 	; 05/12/2021
  3856 00002131 52                  <1> 	push	edx
  3857 00002132 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3858 00002134 E8C4020000          <1> 	call	GET_PARM		; "
  3859                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3860                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3861                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3862                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3863                              <1> 	;mov	cx, ax
  3864                              <1> 	; 05/12/2021
  3865 00002139 29C9                <1> 	sub	ecx, ecx
  3866 0000213B 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3867 0000213D D1E1                <1> 	shl	ecx, 1
  3868 0000213F D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3869 00002141 6649                <1> 	dec	cx
  3870                              <1> 	;pop	dx			; *
  3871                              <1> 	; 05/12/2021
  3872 00002143 5A                  <1> 	pop	edx
  3873 00002144 6601CA              <1> 	add	dx, cx			; check for overflow
  3874 00002147 72D5                <1> 	jc	short dma_bnd_err
  3875                              <1> 	;
  3876 00002149 6629CA              <1> 	sub	dx, cx			; Restore start address
  3877                              <1> 	;
  3878 0000214C B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3879 0000214E FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3880 0000214F E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3881                              <1> 	IODELAY				; WAIT FOR I/O
  2077 00002151 EB00                <2>  jmp short $+2
  2078 00002153 EB00                <2>  jmp short $+2
  3882 00002155 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3883 00002157 89D0                <1> 	mov	eax,edx			; Buffer address
  3884 00002159 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3885                              <1> 	IODELAY				; WAIT FOR I/O
  2077 0000215B EB00                <2>  jmp short $+2
  2078 0000215D EB00                <2>  jmp short $+2
  3886 0000215F 88E0                <1> 	MOV	AL,AH
  3887 00002161 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3888 00002163 C1E810              <1> 	shr	eax,16
  3889                              <1> 	IODELAY				; I/O WAIT STATE
  2077 00002166 EB00                <2>  jmp short $+2
  2078 00002168 EB00                <2>  jmp short $+2
  3890 0000216A E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3891                              <1> 	IODELAY
  2077 0000216C EB00                <2>  jmp short $+2
  2078 0000216E EB00                <2>  jmp short $+2
  3892 00002170 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3893 00002173 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3894                              <1> 	IODELAY				; WAIT FOR I/O
  2077 00002175 EB00                <2>  jmp short $+2
  2078 00002177 EB00                <2>  jmp short $+2
  3895 00002179 88E0                <1> 	MOV	AL,AH
  3896 0000217B E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3897                              <1> 	IODELAY
  2077 0000217D EB00                <2>  jmp short $+2
  2078 0000217F EB00                <2>  jmp short $+2
  3898 00002181 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3899 00002182 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3900 00002184 E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3901 00002186 C3                  <1> 	retn
  3902                              <1> 
  3903                              <1> ;; 08/02/2015 - Protected Mode Modification
  3904                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3905                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3906                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3907                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3908                              <1> ;;	IODELAY
  3909                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3910                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3911                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3912                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3913                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3914                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3915                              <1> ;;	;JNC	short J33A
  3916                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3917                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3918                              <1> ;;;J33A:
  3919                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3920                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3921                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3922                              <1> ;;	IODELAY
  3923                              <1> ;;	MOV	AL,AH
  3924                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3925                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3926                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3927                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3928                              <1> ;;	IODELAY
  3929                              <1> ;;	;AND	AL,00001111B
  3930                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3931                              <1> ;;
  3932                              <1> ;;;----- DETERMINE COUNT
  3933                              <1> ;;	sub	eax, eax ; 08/02/2015
  3934                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3935                              <1> ;;	CALL	GET_PARM		; "
  3936                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  3937                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  3938                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3939                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3940                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  3941                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3942                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3943                              <1> ;;	IODELAY
  3944                              <1> ;;	MOV	AL, AH
  3945                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3946                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3947                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  3948                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  3949                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3950                              <1> ;;	add	ecx, eax ; 08/02/2015
  3951                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3952                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3953                              <1> ;;	SIODELAY
  3954                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3955                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  3956                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  3957                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  3958                              <1> ;;	jz	short FMTDMA_OK
  3959                              <1> ;;	stc	; 20/02/2015
  3960                              <1> ;;fmtdma_bnd_err:
  3961                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3962                              <1> ;;FMTDMA_OK:
  3963                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3964                              <1> 
  3965                              <1> ;-------------------------------------------------------------------------------
  3966                              <1> ; NEC_INIT	
  3967                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  3968                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  3969                              <1> ;
  3970                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  3971                              <1> ;
  3972                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3973                              <1> ;-------------------------------------------------------------------------------
  3974                              <1> NEC_INIT:
  3975                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3976                              <1> 	; 05/12/2021
  3977 00002187 50                  <1> 	push	eax
  3978 00002188 E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  3979                              <1> 
  3980                              <1> ;-----	DO THE SEEK OPERATION
  3981                              <1> 
  3982 0000218D 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  3983 00002190 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  3984                              <1> 	;POP	AX			; RECOVER COMMAND
  3985                              <1> 	; 05/12/2021
  3986 00002195 58                  <1> 	pop	eax
  3987 00002196 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  3988 00002198 BB[B6210000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  3989 0000219D 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  3990                              <1> 
  3991                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  3992                              <1> 
  3993 0000219E E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  3994 000021A3 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  3995 000021A6 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  3996 000021A8 C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  3997 000021AB 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  3998 000021AE 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  3999 000021B0 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4000 000021B5 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4001                              <1> ER_1:
  4002 000021B6 C3                  <1> 	RETn
  4003                              <1> 
  4004                              <1> ;-------------------------------------------------------------------------------
  4005                              <1> ; RWV_COM
  4006                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4007                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4008                              <1> ;
  4009                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4010                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4011                              <1> ;-------------------------------------------------------------------------------
  4012                              <1> RWV_COM:
  4013 000021B7 B8[02220000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4014 000021BC 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4015 000021BD 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4016 000021C0 E83E030000          <1> 	CALL	NEC_OUTPUT
  4017 000021C5 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4018 000021C8 E836030000          <1> 	CALL	NEC_OUTPUT
  4019 000021CD 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4020 000021D0 E82E030000          <1> 	CALL	NEC_OUTPUT
  4021 000021D5 B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4022 000021D7 E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4023 000021DC E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4024 000021E1 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4025 000021E3 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4026 000021E8 E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4027 000021ED 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4028                              <1> _R15:
  4029 000021F0 E80E030000          <1> 	CALL	NEC_OUTPUT
  4030 000021F5 B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4031 000021F7 E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4032 000021FC E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4033 00002201 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4034                              <1> ER_2:
  4035 00002202 C3                  <1> 	RETn
  4036                              <1> 
  4037                              <1> ;-------------------------------------------------------------------------------
  4038                              <1> ; NEC_TERM
  4039                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4040                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4041                              <1> ;
  4042                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4043                              <1> ;-------------------------------------------------------------------------------
  4044                              <1> NEC_TERM:
  4045                              <1> 
  4046                              <1> ;-----	LET THE OPERATION HAPPEN
  4047                              <1> 
  4048 00002203 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4049 00002204 E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4050 00002209 9C                  <1> 	PUSHFd	; 05/12/2021
  4051 0000220A E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4052 0000220F 724B                <1> 	JC	short SET_END_POP
  4053 00002211 9D                  <1> 	POPFd	; 05/12/2021
  4054 00002212 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4055                              <1> 
  4056                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4057                              <1> 
  4058 00002214 FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4059 00002215 BE[BD700000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4060 0000221A AC                  <1> 	lodsb				; GET ST0
  4061 0000221B 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4062 0000221D 7433                <1> 	JZ	short SET_END
  4063 0000221F 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4064 00002221 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4065                              <1> 
  4066                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4067                              <1> 
  4068 00002223 AC                  <1> 	lodsb				; GET ST1
  4069 00002224 D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4070 00002226 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4071 00002228 7222                <1> 	JC	short J19
  4072 0000222A C0E002              <1> 	SAL	AL,2
  4073 0000222D B410                <1> 	MOV	AH,BAD_CRC
  4074 0000222F 721B                <1> 	JC	short J19
  4075 00002231 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4076 00002233 B408                <1> 	MOV	AH,BAD_DMA
  4077 00002235 7215                <1> 	JC	short J19
  4078 00002237 C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4079 0000223A B404                <1> 	MOV	AH,RECORD_NOT_FND
  4080 0000223C 720E                <1> 	JC	short J19
  4081 0000223E D0E0                <1> 	SAL	AL,1
  4082 00002240 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4083 00002242 7208                <1> 	JC	short J19
  4084 00002244 D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4085 00002246 B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4086 00002248 7202                <1> 	JC	short J19
  4087                              <1> 
  4088                              <1> ;----- 	NEC MUST HAVE FAILED
  4089                              <1> J18:
  4090 0000224A B420                <1> 	MOV	AH,BAD_NEC
  4091                              <1> J19:
  4092 0000224C 0825[BC700000]      <1> 	OR	[DSKETTE_STATUS],AH
  4093                              <1> SET_END:
  4094 00002252 803D[BC700000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4095 00002259 F5                  <1> 	CMC
  4096 0000225A 5E                  <1> 	POP	eSI
  4097 0000225B C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4098                              <1> 
  4099                              <1> SET_END_POP:
  4100 0000225C 9D                  <1> 	POPFd	; 05/12/2021
  4101 0000225D EBF3                <1> 	JMP	SHORT SET_END
  4102                              <1> 
  4103                              <1> ;-------------------------------------------------------------------------------
  4104                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4105                              <1> ;-------------------------------------------------------------------------------
  4106                              <1> DSTATE:
  4107 0000225F 803D[BC700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4108 00002266 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4109 00002268 808F[C9700000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4110 0000226F F687[C9700000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4111 00002276 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4112 00002278 8A87[C9700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4113 0000227E 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4114 00002280 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4115 00002282 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4116                              <1> 
  4117                              <1> ;----- 	CHECK IF IT IS 1.44M
  4118                              <1> 
  4119 00002284 E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4120                              <1> 	;;20/02/2015
  4121                              <1> 	;;JC	short M_12		; CMOS BAD
  4122 00002289 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4123 0000228B 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4124 0000228D 7410                <1> 	JE	short M_12		; YES
  4125                              <1> M_720:
  4126 0000228F 80A7[C9700000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4127 00002296 808F[C9700000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4128 0000229D EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4129                              <1> M_12:	
  4130 0000229F 808F[C9700000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4131                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4132                              <1> SETBAC:
  4133 000022A6 C3                  <1> 	RETn
  4134                              <1> 
  4135                              <1> ;-------------------------------------------------------------------------------
  4136                              <1> ; RETRY	
  4137                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4138                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4139                              <1> ;
  4140                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4141                              <1> ;-------------------------------------------------------------------------------
  4142                              <1> RETRY:
  4143 000022A7 803D[BC700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4144 000022AE 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4145 000022B0 803D[BC700000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4146 000022B7 743C                <1> 	JZ	short NO_RETRY
  4147 000022B9 8AA7[C9700000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4148 000022BF F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4149 000022C2 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4150 000022C4 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4151 000022C7 8A2D[C4700000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4152 000022CD C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4153 000022D0 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4154 000022D3 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4155 000022D5 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4156                              <1> 
  4157                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4158                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4159                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4160                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4161                              <1> 
  4162 000022D7 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4163 000022DA D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4164 000022DC 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4165 000022DF 80A7[C9700000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4166                              <1> 					; RATE, DBL STEP OFF
  4167 000022E6 08A7[C9700000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4168 000022EC C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4169 000022F3 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4170 000022F4 C3                  <1> 	RETn				; RETRY RETURN
  4171                              <1> 
  4172                              <1> NO_RETRY:
  4173 000022F5 F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4174 000022F6 C3                  <1> 	RETn				; NO RETRY RETURN
  4175                              <1> 
  4176                              <1> ;-------------------------------------------------------------------------------
  4177                              <1> ; NUM_TRANS
  4178                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4179                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4180                              <1> ;
  4181                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4182                              <1> ;		SI-HI  = HEAD
  4183                              <1> ;		[BP]   = START SECTOR
  4184                              <1> ;
  4185                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4186                              <1> ;-------------------------------------------------------------------------------
  4187                              <1> NUM_TRANS:
  4188 000022F7 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4189 000022F9 803D[BC700000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4190                              <1> 	; 05/12/2021
  4191 00002300 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4192 00002302 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4193 00002304 E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4194 00002309 8A1D[C2700000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4195 0000230F 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4196 00002312 3A2D[C1700000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4197 00002318 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4198 0000231A 8A2D[C0700000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4199 00002320 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4200 00002323 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4201 00002325 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4202                              <1> DIF_HD:
  4203 00002327 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4204                              <1> SAME_TRK:
  4205 00002329 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4206 0000232C 88D8                <1> 	MOV	AL,BL			; TO AL
  4207                              <1> NT_OUT:
  4208 0000232E C3                  <1> 	RETn
  4209                              <1> 
  4210                              <1> ;-------------------------------------------------------------------------------
  4211                              <1> ; SETUP_END
  4212                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4213                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4214                              <1> ;
  4215                              <1> ; ON EXIT:
  4216                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4217                              <1> ;-------------------------------------------------------------------------------
  4218                              <1> SETUP_END:
  4219 0000232F B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4220                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4221 00002331 50                  <1> 	push	eax ; 05/12/2021
  4222 00002332 E8C6000000          <1> 	CALL	GET_PARM
  4223 00002337 8825[BB700000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4224                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4225 0000233D 58                  <1> 	pop	eax ; 05/12/2021
  4226 0000233E 8A25[BC700000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4227 00002344 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4228 00002346 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4229 00002348 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4230                              <1> NUN_ERR: 
  4231 0000234A 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4232 0000234D F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4233 0000234E C3                  <1> 	RETn
  4234                              <1> 
  4235                              <1> ;-------------------------------------------------------------------------------
  4236                              <1> ; SETUP_DBL
  4237                              <1> ;	CHECK DOUBLE STEP.
  4238                              <1> ;
  4239                              <1> ; ON ENTRY :	DI = DRIVE
  4240                              <1> ;
  4241                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4242                              <1> ;-------------------------------------------------------------------------------
  4243                              <1> SETUP_DBL:
  4244 0000234F 8AA7[C9700000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4245 00002355 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4246 00002358 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4247                              <1> 
  4248                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4249                              <1> 
  4250 0000235A C605[B9700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4251 00002361 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4252 00002366 B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4253 00002368 E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4254 0000236D E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4255 00002372 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4256                              <1> 
  4257                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4258                              <1> 
  4259 00002374 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4260 00002378 F687[C9700000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4261 0000237F 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4262 00002381 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4263                              <1> 
  4264                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4265                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4266                              <1> ;	THEN SET DOUBLE STEP ON.
  4267                              <1> 
  4268                              <1> CNT_OK:
  4269 00002383 C605[BB700000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4270                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4271                              <1> 	; 05/12/2021
  4272 0000238A 51                  <1> 	push	ecx
  4273 0000238B C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4274 00002392 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4275 00002395 D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4276 00002397 C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4277                              <1> 	;PUSH	AX			; SAVE HEAD
  4278                              <1> 	; 05/12/2021
  4279 0000239A 50                  <1> 	push	eax
  4280 0000239B E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4281                              <1> 	;POP	AX			; RESTORE HEAD
  4282                              <1> 	; 05/12/2021
  4283 000023A0 58                  <1> 	pop	eax
  4284 000023A1 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4285 000023A4 E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4286 000023A9 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4287 000023AA 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4288 000023AF 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4289                              <1> 	;POP	CX			; RESTORE COUNT
  4290                              <1> 	; 05/12/2021
  4291 000023B0 59                  <1> 	pop	ecx
  4292 000023B1 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4293 000023B3 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4294 000023B5 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4295 000023B7 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4296                              <1> 
  4297                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4298                              <1> 
  4299                              <1> SD_ERR:	
  4300 000023B9 F9                  <1> 	STC				; SET CARRY FOR ERROR
  4301 000023BA C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4302                              <1> 
  4303                              <1> DO_CHK:
  4304 000023BB 8A0D[C0700000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4305 000023C1 888F[CD700000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4306 000023C7 D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4307 000023C9 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4308 000023CB 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4309 000023CD 808F[C9700000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4310                              <1> NO_DBL:
  4311 000023D4 F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4312 000023D5 C3                  <1> 	RETn
  4313                              <1> 
  4314                              <1> ;-------------------------------------------------------------------------------
  4315                              <1> ; READ_ID
  4316                              <1> ;	READ ID FUNCTION.
  4317                              <1> ;
  4318                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4319                              <1> ;
  4320                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4321                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4322                              <1> ;-------------------------------------------------------------------------------
  4323                              <1> READ_ID:
  4324 000023D6 B8[F3230000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4325 000023DB 50                  <1> 	PUSH	eAX
  4326 000023DC B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4327 000023DE E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4328 000023E3 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4329 000023E6 88C4                <1> 	MOV	AH,AL
  4330 000023E8 E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4331 000023ED E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4332 000023F2 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4333                              <1> ER_3:
  4334 000023F3 C3                  <1> 	RETn
  4335                              <1> 
  4336                              <1> ;-------------------------------------------------------------------------------
  4337                              <1> ; CMOS_TYPE
  4338                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4339                              <1> ;
  4340                              <1> ; ON ENTRY:	DI = DRIVE #
  4341                              <1> ;
  4342                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4343                              <1> ;-------------------------------------------------------------------------------
  4344                              <1> 
  4345                              <1> CMOS_TYPE: ; 11/12/2014
  4346 000023F4 8A87[2E6B0000]      <1> 	mov	al, [eDI+fd0_type]
  4347 000023FA 20C0                <1> 	and 	al, al ; 18/12/2014
  4348 000023FC C3                  <1> 	retn
  4349                              <1> 
  4350                              <1> ;CMOS_TYPE:
  4351                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4352                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4353                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4354                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4355                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4356                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4357                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4358                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4359                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4360                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4361                              <1> ;TB:
  4362                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4363                              <1> ;BAD_CM:
  4364                              <1> ;	RETn				; CY, STATUS OF READ
  4365                              <1> 
  4366                              <1> ;-------------------------------------------------------------------------------
  4367                              <1> ; GET_PARM
  4368                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4369                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4370                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4371                              <1> ;	THE PARAMETER IN DL.
  4372                              <1> ;
  4373                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4374                              <1> ;
  4375                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4376                              <1> ;		AL,DH DESTROYED
  4377                              <1> ;-------------------------------------------------------------------------------
  4378                              <1> GET_PARM:
  4379                              <1> 	;PUSH	DS
  4380 000023FD 56                  <1> 	PUSH	eSI
  4381                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4382                              <1>     	;MOV	DS,AX
  4383                              <1> 	;;mov	ax, cs
  4384                              <1> 	;;mov	ds, ax
  4385                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4386 000023FE 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4387                              <1> 	;SUB	BH,BH			; BX = INDEX
  4388 00002400 81E3FF000000        <1> 	and	ebx, 0FFh
  4389                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4390                              <1> 	;
  4391                              <1> 	; 17/12/2014
  4392 00002406 66A1[216B0000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4393 0000240C 38E0                <1> 	cmp	al, ah
  4394 0000240E 7425                <1> 	je	short gpndc
  4395 00002410 A2[226B0000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4396 00002415 53                  <1> 	push	ebx ; 08/02/2015
  4397 00002416 88C3                <1> 	mov	bl, al 
  4398                              <1> 	; 11/12/2014
  4399 00002418 8A83[2E6B0000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4400                              <1> 	; 18/12/2014
  4401 0000241E 20C0                <1> 	and	al, al
  4402 00002420 7507                <1> 	jnz	short gpdtc
  4403 00002422 BB[0B6B0000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4404 00002427 EB05                <1>         jmp     short gpdpu
  4405                              <1> gpdtc:	
  4406 00002429 E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4407                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4408                              <1> gpdpu:
  4409 0000242E 891D[A86A0000]      <1> 	mov	[DISK_POINTER], ebx
  4410 00002434 5B                  <1> 	pop	ebx
  4411                              <1> gpndc:
  4412 00002435 8B35[A86A0000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4413 0000243B 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4414 0000243E 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4415 00002440 5E                  <1> 	POP	eSI
  4416                              <1> 	;POP	DS
  4417 00002441 C3                  <1> 	RETn
  4418                              <1> 
  4419                              <1> ;-------------------------------------------------------------------------------
  4420                              <1> ; MOTOR_ON
  4421                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4422                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4423                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4424                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4425                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4426                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4427                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4428                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4429                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4430                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4431                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4432                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4433                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4434                              <1> ;
  4435                              <1> ; ON ENTRY:	DI = DRIVE #
  4436                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4437                              <1> ;-------------------------------------------------------------------------------
  4438                              <1> MOTOR_ON:
  4439 00002442 53                  <1> 	PUSH	eBX			; SAVE REG.
  4440 00002443 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4441 00002448 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4442 0000244A E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4443 0000244F E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4444                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4445                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4446                              <1> M_WAIT:
  4447 00002454 B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4448 00002456 E8A2FFFFFF          <1> 	CALL	GET_PARM
  4449                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4450                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4451                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4452 0000245B 80FC08              <1> 	cmp	ah, 8
  4453                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4454 0000245E 7702                <1> 	ja	short J13
  4455                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4456 00002460 B408                <1> 	mov	ah, 8
  4457                              <1> 
  4458                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4459                              <1> GP2:	
  4460                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4461                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4462 00002462 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4463 00002467 E862F1FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4464                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4465 0000246C FECC                <1> 	dec	ah
  4466 0000246E 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4467                              <1> MOT_IS_ON:
  4468 00002470 5B                  <1> 	POP	eBX			; RESTORE REG.
  4469 00002471 C3                  <1> 	RETn
  4470                              <1> 
  4471                              <1> ;-------------------------------------------------------------------------------
  4472                              <1> ; TURN_ON
  4473                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4474                              <1> ;
  4475                              <1> ; ON ENTRY:	DI = DRIVE #
  4476                              <1> ;
  4477                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4478                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4479                              <1> ;		AX,BX,CX,DX DESTROYED
  4480                              <1> ;-------------------------------------------------------------------------------
  4481                              <1> TURN_ON:
  4482 00002472 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4483 00002474 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4484 00002476 C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4485 00002479 FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4486 0000247A C605[BB700000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4487 00002481 A0[BA700000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4488 00002486 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4489 00002488 B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4490 0000248A D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4491                              <1> 
  4492                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4493                              <1> ;  BL = DRIVE SELECT DESIRED
  4494                              <1> ;  AH = MOTOR ON MASK DESIRED
  4495                              <1> 
  4496 0000248C 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4497 0000248E 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4498 00002490 8425[BA700000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4499 00002496 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4500                              <1> 
  4501                              <1> TURN_IT_ON:
  4502 00002498 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4503 0000249A 8A3D[BA700000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4504 000024A0 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4505 000024A3 8025[BA700000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4506 000024AA 0825[BA700000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4507 000024B0 A0[BA700000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4508 000024B5 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4509 000024B7 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4510 000024BA FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4511 000024BB 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4512 000024BD C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4513 000024C0 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4514 000024C2 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4515 000024C6 EE                  <1> 	OUT	DX,AL
  4516 000024C7 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4517                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4518 000024C9 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4519 000024CB F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4520 000024CC C3                  <1> 	RETn
  4521                              <1> 
  4522                              <1> NO_MOT_WAIT:
  4523 000024CD FB                  <1> 	sti
  4524                              <1> no_mot_w1: ; 27/02/2015
  4525 000024CE F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4526                              <1> 	;STI				; INTERRUPTS BACK ON
  4527 000024CF C3                  <1> 	RETn
  4528                              <1> 
  4529                              <1> ;-------------------------------------------------------------------------------
  4530                              <1> ; HD_WAIT
  4531                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4532                              <1> ;
  4533                              <1> ; ON ENTRY:	DI = DRIVE #
  4534                              <1> ;
  4535                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4536                              <1> ;-------------------------------------------------------------------------------
  4537                              <1> HD_WAIT:
  4538 000024D0 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4539 000024D2 E826FFFFFF          <1> 	CALL	GET_PARM
  4540 000024D7 08E4                <1> 	or	ah, ah	; 17/12/2014
  4541 000024D9 7519                <1> 	jnz	short DO_WAT
  4542 000024DB F605[BA700000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4543                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4544                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4545                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4546 000024E2 741E                <1> 	jz	short HW_DONE
  4547 000024E4 B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4548 000024E6 8A87[C9700000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4549 000024EC 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4550 000024EE 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4551 000024F0 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4552                              <1> ;GP3:
  4553 000024F2 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4554                              <1> ;	JMP	SHORT DO_WAT
  4555                              <1> 
  4556                              <1> ;ISNT_WRITE:
  4557                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4558                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4559                              <1> 
  4560                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4561                              <1> DO_WAT:
  4562                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4563                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4564                              <1> J29:					; 	1 MILLISECOND LOOP
  4565                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4566 000024F4 B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4567 000024F9 E8D0F0FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4568                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4569 000024FE FECC                <1> 	dec	ah
  4570 00002500 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4571                              <1> HW_DONE:
  4572 00002502 C3                  <1> 	RETn
  4573                              <1> 
  4574                              <1> ;-------------------------------------------------------------------------------
  4575                              <1> ; NEC_OUTPUT
  4576                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4577                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4578                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4579                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4580                              <1> ; 
  4581                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4582                              <1> ;
  4583                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4584                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4585                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4586                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4587                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4588                              <1> ;		AX,CX,DX DESTROYED
  4589                              <1> ;-------------------------------------------------------------------------------
  4590                              <1> 
  4591                              <1> ; 09/12/2014 [Erdogan Tan] 
  4592                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4593                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4594                              <1> ;	This read only register facilitates the transfer of data between
  4595                              <1> ;	the system microprocessor and the controller.
  4596                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4597                              <1> ;	  with the system micrprocessor.
  4598                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4599                              <1> ;	  the transfer is to the controller.
  4600                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4601                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4602                              <1> ; Bit 3 - Reserved.
  4603                              <1> ; Bit 2 - Reserved.
  4604                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4605                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4606                              <1> 
  4607                              <1> ; Data Register (3F5h)
  4608                              <1> ; This read/write register passes data, commands and parameters, and provides
  4609                              <1> ; diskette status information.
  4610                              <1>   		
  4611                              <1> NEC_OUTPUT:
  4612                              <1> 	;PUSH	BX			; SAVE REG.
  4613 00002503 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4614                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4615                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4616                              <1> 	; 16/12/2014
  4617                              <1> 	; waiting for (max.) 0.5 seconds
  4618                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4619                              <1> 	;
  4620                              <1> 	; 17/12/2014
  4621                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4622                              <1> 	;
  4623                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4624                              <1> 	;		go on.
  4625                              <1> 	;INPUT:
  4626                              <1> 	;	AH=Mask for isolation bits.
  4627                              <1> 	;	AL=pattern to look for.
  4628                              <1> 	;	DX=Port to test for
  4629                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4630                              <1> 	;	     (normally 30 microseconds per period.)
  4631                              <1> 	;
  4632                              <1> 	;WFP_SHORT:  
  4633                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4634                              <1> 	;
  4635                              <1> 
  4636                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4637                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4638 00002507 B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4639                              <1> ;
  4640                              <1> ;WFPS_OUTER_LP:
  4641                              <1> ;	;
  4642                              <1> ;WFPS_CHECK_PORT:
  4643                              <1> J23:
  4644 0000250C EC                  <1> 	IN	AL,DX			; GET STATUS
  4645 0000250D 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4646 0000250F 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4647 00002511 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4648                              <1> WFPS_HI:
  4649 00002513 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4650 00002515 A810                <1> 	TEST	AL,010H			; transition on memory
  4651 00002517 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4652                              <1> WFPS_LO:
  4653 00002519 E461                <1> 	IN	AL, PORT_B		; SYS1
  4654 0000251B A810                <1> 	TEST	AL,010H
  4655 0000251D 74FA                <1> 	JZ	SHORT WFPS_LO
  4656                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4657 0000251F E2EB                <1> 	loop	J23	; 27/02/2015
  4658                              <1> ;	;
  4659                              <1> ;	dec	bl
  4660                              <1> ;	jnz	short WFPS_OUTER_LP
  4661                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4662                              <1> ;J23:
  4663                              <1> ;	IN	AL,DX			; GET STATUS
  4664                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4665                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4666                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4667                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4668                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4669                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4670                              <1>    
  4671                              <1> 	;;27/02/2015
  4672                              <1> 	;16/12/2014
  4673                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4674                              <1> 	;;jb	short J23
  4675                              <1> 
  4676                              <1> ;WFPS_TIMEOUT:
  4677                              <1> 
  4678                              <1> ;-----	FALL THRU TO ERROR RETURN
  4679                              <1> 
  4680 00002521 800D[BC700000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4681                              <1> 	;POP	BX			; RESTORE REG.
  4682 00002528 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4683 00002529 F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4684 0000252A C3                  <1> 	RETn
  4685                              <1> 
  4686                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4687                              <1> 
  4688                              <1> J27:	
  4689 0000252B 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4690 0000252D 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4691 0000252F EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4692                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4693                              <1> 	; 27/02/2015
  4694 00002530 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE FLAGS
  4695                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4696 00002531 29C9                <1> 	sub	ecx, ecx
  4697 00002533 B103                <1> 	mov	cl, 3 ; 05/12/2021
  4698 00002535 E894F0FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4699 0000253A 9D                  <1> 	POPFd	; 05/12/2021			; RESTORE FLAGS FOR EXIT
  4700                              <1> 	;POP	BX			; RESTORE REG
  4701 0000253B C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4702                              <1> 
  4703                              <1> ;-------------------------------------------------------------------------------
  4704                              <1> ; SEEK
  4705                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4706                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4707                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4708                              <1> ;
  4709                              <1> ; ON ENTRY:	DI = DRIVE #
  4710                              <1> ;		CH = TRACK #
  4711                              <1> ;
  4712                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4713                              <1> ;		AX,BX,CX DX DESTROYED
  4714                              <1> ;-------------------------------------------------------------------------------
  4715                              <1> SEEK:
  4716 0000253C 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4717 0000253E B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4718 00002540 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4719 00002542 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4720 00002544 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4721 00002546 8405[B9700000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4722 0000254C 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4723                              <1> 
  4724 0000254E 0805[B9700000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4725 00002554 E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4726 00002559 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4727                              <1> 
  4728                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4729                              <1> 
  4730 0000255B C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4731 00002562 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4732 00002567 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4733                              <1> 
  4734                              <1> AFT_RECAL:
  4735 00002569 C687[CD700000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4736 00002570 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4737 00002572 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4738                              <1> 
  4739                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4740                              <1> 
  4741 00002574 F687[C9700000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4742 0000257B 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4743 0000257D D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4744                              <1> 
  4745 0000257F 3AAF[CD700000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4746 00002585 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4747                              <1> 
  4748 00002587 BA[BA250000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4749 0000258C 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4750 0000258D 88AF[CD700000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4751 00002593 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4752 00002595 E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4753 0000259A 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4754 0000259C 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4755 0000259E E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4756 000025A3 8AA7[CD700000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4757 000025A9 E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4758 000025AE E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4759                              <1> 
  4760                              <1> ;-----	WAIT FOR HEAD SETTLE
  4761                              <1> 
  4762                              <1> DO_WAIT:
  4763 000025B3 9C                  <1> 	PUSHFd	; 05/12/2021		; SAVE STATUS
  4764 000025B4 E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4765 000025B9 9D                  <1> 	POPFd	; 05/12/2021		; RESTORE STATUS
  4766                              <1> RB:
  4767                              <1> NEC_ERR:
  4768                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4769                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4770 000025BA C3                  <1> 	RETn				; RETURN TO CALLER
  4771                              <1> 
  4772                              <1> ;-------------------------------------------------------------------------------
  4773                              <1> ; RECAL
  4774                              <1> ;	RECALIBRATE DRIVE
  4775                              <1> ;
  4776                              <1> ; ON ENTRY:	DI = DRIVE #
  4777                              <1> ;
  4778                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4779                              <1> ;-------------------------------------------------------------------------------
  4780                              <1> RECAL:
  4781                              <1> 	;PUSH	CX
  4782                              <1> 	; 05/12/2021
  4783 000025BB 51                  <1> 	push	ecx
  4784 000025BC B8[D8250000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4785 000025C1 50                  <1> 	PUSH	eAX
  4786 000025C2 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4787 000025C4 E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4788 000025C9 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4789 000025CB 88DC                <1> 	MOV	AH,BL
  4790 000025CD E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4791 000025D2 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4792 000025D7 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4793                              <1> RC_BACK:
  4794                              <1> 	;POP	CX
  4795                              <1> 	; 05/12/2021
  4796 000025D8 59                  <1> 	pop	ecx
  4797 000025D9 C3                  <1> 	RETn
  4798                              <1> 
  4799                              <1> ;-------------------------------------------------------------------------------
  4800                              <1> ; CHK_STAT_2
  4801                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4802                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4803                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4804                              <1> ;
  4805                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4806                              <1> ;-------------------------------------------------------------------------------
  4807                              <1> CHK_STAT_2:
  4808 000025DA B8[02260000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4809 000025DF 50                  <1> 	PUSH	eAX
  4810 000025E0 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4811 000025E5 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4812 000025E7 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4813 000025E9 E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4814 000025EE E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4815 000025F3 720C                <1> 	JC	short J34
  4816 000025F5 A0[BD700000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4817 000025FA 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4818 000025FC 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4819 000025FE 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4820 00002600 F8                  <1> 	CLC				; GOOD RETURN
  4821                              <1> J34:
  4822 00002601 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4823                              <1> CS_BACK:
  4824 00002602 C3                  <1> 	RETn
  4825                              <1> J35:
  4826 00002603 800D[BC700000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4827 0000260A F9                  <1> 	STC				; ERROR RETURN CODE
  4828 0000260B EBF4                <1> 	JMP	SHORT J34
  4829                              <1> 
  4830                              <1> ;-------------------------------------------------------------------------------
  4831                              <1> ; WAIT_INT
  4832                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4833                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4834                              <1> ;	IF THE DRIVE IS NOT READY.
  4835                              <1> ;
  4836                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4837                              <1> ;-------------------------------------------------------------------------------
  4838                              <1> 
  4839                              <1> ; 17/12/2014
  4840                              <1> ; 2.5 seconds waiting !
  4841                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4842                              <1> ; amount of time to wait for completion interrupt from NEC.
  4843                              <1> 
  4844                              <1> 
  4845                              <1> WAIT_INT:
  4846 0000260D FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4847 0000260E F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4848                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4849                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4850                              <1> 
  4851                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4852                              <1> 	;
  4853                              <1> 	;WAIT_FOR_MEM:	
  4854                              <1> 	;	Waits for a bit at a specified memory location pointed
  4855                              <1> 	;	to by ES:[DI] to become set.
  4856                              <1> 	;INPUT:
  4857                              <1> 	;	AH=Mask to test with.
  4858                              <1> 	;	ES:[DI] = memory location to watch.
  4859                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4860                              <1> 	;	     (normally 30 microseconds per period.)
  4861                              <1> 
  4862                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4863                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4864                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4865                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4866                              <1> 	; 27/02/2015
  4867 0000260F B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4868                              <1> WFMS_CHECK_MEM:
  4869 00002614 F605[B9700000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4870 0000261B 7516                <1>         jnz     short J37
  4871                              <1> WFMS_HI:
  4872 0000261D E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4873 0000261F A810                <1> 	TEST	AL,010H			; transition on memory
  4874 00002621 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4875                              <1> WFMS_LO:
  4876 00002623 E461                <1> 	IN	AL,PORT_B		;SYS1
  4877 00002625 A810                <1> 	TEST	AL,010H
  4878 00002627 74FA                <1> 	JZ	SHORT WFMS_LO
  4879 00002629 E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4880                              <1> ;WFMS_OUTER_LP:
  4881                              <1> ;;	or	bl, bl			; check outer counter
  4882                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4883                              <1> ;	dec	bl
  4884                              <1> ;	jz	short J36A	
  4885                              <1> ;	jmp	short WFMS_CHECK_MEM
  4886                              <1> 
  4887                              <1> 	;17/12/2014
  4888                              <1> 	;16/12/2014
  4889                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4890                              <1> ;J36:
  4891                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4892                              <1> ;	JNZ	short J37
  4893                              <1> 	;16/12/2014
  4894                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4895                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4896                              <1> 	;JNZ	short J36
  4897                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4898                              <1> ;	jb	short J36
  4899                              <1> 
  4900                              <1> ;WFMS_TIMEOUT:
  4901                              <1> ;J36A:
  4902 0000262B 800D[BC700000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4903 00002632 F9                  <1> 	STC				; ERROR RETURN
  4904                              <1> J37:
  4905 00002633 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4906 00002634 8025[B9700000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4907 0000263B 9D                  <1> 	POPF				; RECOVER CARRY
  4908 0000263C C3                  <1> 	RETn				; GOOD RETURN CODE
  4909                              <1> 
  4910                              <1> ;-------------------------------------------------------------------------------
  4911                              <1> ; RESULTS
  4912                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4913                              <1> ;	FOLLOWING AN INTERRUPT.
  4914                              <1> ;
  4915                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4916                              <1> ;		AX,BX,CX,DX DESTROYED
  4917                              <1> ;-------------------------------------------------------------------------------
  4918                              <1> RESULTS:
  4919 0000263D 57                  <1> 	PUSH	eDI
  4920 0000263E BF[BD700000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4921 00002643 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4922 00002645 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4923                              <1> 
  4924                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4925                              <1> 
  4926                              <1> _R10: 
  4927                              <1> 	; 16/12/2014
  4928                              <1> 	; wait for (max) 0.5 seconds
  4929                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  4930                              <1> 	;XOR	CX,CX			; COUNTER
  4931                              <1> 
  4932                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  4933                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  4934                              <1> 	; 27/02/2015
  4935 00002649 B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  4936                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  4937                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  4938                              <1> 
  4939                              <1> WFPSR_OUTER_LP:
  4940                              <1> 	;
  4941                              <1> WFPSR_CHECK_PORT:
  4942                              <1> J39:					; WAIT FOR MASTER
  4943 0000264E EC                  <1> 	IN	AL,DX			; GET STATUS
  4944 0000264F 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4945 00002651 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4946 00002653 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  4947                              <1> WFPSR_HI:
  4948 00002655 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4949 00002657 A810                <1> 	TEST	AL,010H			; transition on memory
  4950 00002659 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  4951                              <1> WFPSR_LO:
  4952 0000265B E461                <1> 	IN	AL, PORT_B		; SYS1
  4953 0000265D A810                <1> 	TEST	AL,010H
  4954 0000265F 74FA                <1> 	JZ	SHORT WFPSR_LO
  4955 00002661 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  4956                              <1> 	;; 27/02/2015
  4957                              <1> 	;;dec	bh
  4958                              <1> 	;;jnz	short WFPSR_OUTER_LP
  4959                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  4960                              <1> 
  4961                              <1> 	;;mov	byte [wait_count], 0
  4962                              <1> ;J39:					; WAIT FOR MASTER
  4963                              <1> ;	IN	AL,DX			; GET STATUS
  4964                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  4965                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  4966                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  4967                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  4968                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  4969                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  4970                              <1> 	;
  4971                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  4972                              <1> 	;;jb	short J39	
  4973                              <1> 
  4974                              <1> ;WFPSR_TIMEOUT:
  4975 00002663 800D[BC700000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4976 0000266A F9                  <1> 	STC				; SET ERROR RETURN
  4977 0000266B EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  4978                              <1> 
  4979                              <1> ;-----	READ IN THE STATUS
  4980                              <1> 
  4981                              <1> J42:
  4982 0000266D EB00                <1> 	JMP	$+2			; I/O DELAY
  4983 0000266F 6642                <1> 	INC	DX			; POINT AT DATA PORT
  4984 00002671 EC                  <1> 	IN	AL,DX			; GET THE DATA
  4985                              <1> 	; 16/12/2014
  4986                              <1> 	NEWIODELAY
  2082 00002672 E6EB                <2>  out 0EBh,al
  4987 00002674 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  4988 00002676 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  4989                              <1> 	; 16/12/2014
  4990                              <1> ;	push	cx
  4991                              <1> ;	mov	cx, 30
  4992                              <1> ;wdw2:
  4993                              <1> ;	NEWIODELAY
  4994                              <1> ;	loop	wdw2
  4995                              <1> ;	pop	cx
  4996                              <1> 
  4997 00002677 B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  4998 0000267C E84DEFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  4999 00002681 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5000 00002683 EC                  <1> 	IN	AL,DX			; GET STATUS
  5001                              <1> 	; 16/12/2014
  5002                              <1> 	NEWIODELAY
  2082 00002684 E6EB                <2>  out 0EBh,al
  5003                              <1> 	;
  5004 00002686 A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5005 00002688 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5006                              <1> 
  5007 0000268A FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5008 0000268C 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5009 0000268E 800D[BC700000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5010 00002695 F9                  <1> 	STC				; SET ERROR FLAG
  5011                              <1> 
  5012                              <1> ;-----	RESULT OPERATION IS DONE
  5013                              <1> POPRES:
  5014 00002696 5F                  <1> 	POP	eDI
  5015 00002697 C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5016                              <1> 
  5017                              <1> ;-------------------------------------------------------------------------------
  5018                              <1> ; READ_DSKCHNG
  5019                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5020                              <1> ;
  5021                              <1> ; ON ENTRY:	DI = DRIVE #
  5022                              <1> ;
  5023                              <1> ; ON EXIT:	DI = DRIVE #
  5024                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5025                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5026                              <1> ;		AX,CX,DX DESTROYED
  5027                              <1> ;-------------------------------------------------------------------------------
  5028                              <1> READ_DSKCHNG:
  5029 00002698 E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5030 0000269D 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5031 000026A1 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5032 000026A2 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5033 000026A4 C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5034                              <1> 
  5035                              <1> ;-------------------------------------------------------------------------------
  5036                              <1> ; DRIVE_DET
  5037                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5038                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5039                              <1> ; ON ENTRY:	DI = DRIVE #
  5040                              <1> ;-------------------------------------------------------------------------------
  5041                              <1> DRIVE_DET:
  5042 000026A5 E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5043 000026AA E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5044 000026AF 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5045 000026B1 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5046 000026B3 E884FEFFFF          <1> 	CALL	SEEK
  5047 000026B8 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5048 000026BA B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5049                              <1> SK_GIN:
  5050 000026BC FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5051                              <1> 	;PUSH	CX			; SAVE TRACK
  5052                              <1> 	; 05/12/2021
  5053 000026BE 51                  <1> 	push	ecx
  5054 000026BF E878FEFFFF          <1> 	CALL	SEEK
  5055 000026C4 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5056 000026C6 B8[01270000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5057 000026CB 50                  <1> 	PUSH	eAX
  5058 000026CC B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5059 000026CE E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5060 000026D3 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5061 000026D6 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5062 000026D8 E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5063 000026DD E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5064 000026E2 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5065                              <1> 	;POP	CX			; RESTORE TRACK
  5066                              <1> 	; 05/12/2021
  5067 000026E3 59                  <1> 	pop	ecx
  5068 000026E4 F605[BD700000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5069 000026EB 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5070 000026ED 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5071 000026EF 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5072                              <1> 
  5073                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5074                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5075                              <1> 
  5076 000026F1 808F[C9700000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5077 000026F8 C3                  <1> 	RETn				; ALL INFORMATION SET
  5078                              <1> IS_80:
  5079 000026F9 808F[C9700000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5080                              <1> DD_BAC:
  5081 00002700 C3                  <1> 	RETn
  5082                              <1> POP_BAC:
  5083                              <1> 	;POP	CX			; THROW AWAY
  5084                              <1> 	; 05/12/2021
  5085 00002701 59                  <1> 	pop	ecx
  5086 00002702 C3                  <1> 	RETn
  5087                              <1> 
  5088                              <1> fdc_int:  
  5089                              <1> 	  ; 30/07/2015	
  5090                              <1> 	  ; 16/02/2015
  5091                              <1> ;int_0Eh: ; 11/12/2014
  5092                              <1> 
  5093                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5094                              <1> ; DISK_INT
  5095                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5096                              <1> ;
  5097                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5098                              <1> ;-------------------------------------------------------------------------------
  5099                              <1> DISK_INT_1:
  5100                              <1> 
  5101                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5102                              <1> 	; 05/12/2021
  5103 00002703 50                  <1> 	push	eax
  5104 00002704 1E                  <1> 	push	ds
  5105 00002705 66B81000            <1> 	mov	ax, KDATA
  5106 00002709 8ED8                <1> 	mov 	ds, ax
  5107 0000270B 800D[B9700000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5108 00002712 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5109 00002714 E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5110 00002716 1F                  <1> 	pop	ds
  5111                              <1> 	;POP	AX			; RECOVER REGISTER
  5112                              <1> 	; 05/12/2021
  5113 00002717 58                  <1> 	pop	eax
  5114 00002718 CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5115                              <1> 
  5116                              <1> ;-------------------------------------------------------------------------------
  5117                              <1> ; DSKETTE_SETUP
  5118                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5119                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5120                              <1> ;-------------------------------------------------------------------------------
  5121                              <1> DSKETTE_SETUP:
  5122                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5123                              <1> 	;PUSH	BX
  5124                              <1> 	;PUSH	CX
  5125 00002719 52                  <1> 	PUSH	eDX
  5126                              <1> 	;PUSH	DI
  5127                              <1> 	;;PUSH	DS
  5128                              <1> 	; 14/12/2014
  5129                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5130                              <1> 	;mov	[DISK_POINTER+2], cs
  5131                              <1> 	;
  5132                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5133 0000271A 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5134 0000271C 66C705[C9700000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5134 00002724 00                  <1>
  5135 00002725 8025[C4700000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5136 0000272C 800D[C4700000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5137 00002733 C605[B9700000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5138 0000273A C605[BB700000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5139 00002741 C605[BA700000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5140 00002748 C605[BC700000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5141                              <1> 	;
  5142                              <1> 	; 28/02/2015
  5143                              <1> 	;mov	word [cfd], 100h 
  5144 0000274F E89DF2FFFF          <1> 	call	DSK_RESET
  5145 00002754 5A                  <1> 	pop	edx
  5146 00002755 C3                  <1> 	retn
  5147                              <1> 
  5148                              <1> ;SUP0:
  5149                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5150                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5151                              <1> ;	; 02/01/2015
  5152                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5153                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5154                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5155                              <1> ;       cmp     byte [fd1_type], 0	
  5156                              <1> ;	jna	short sup1
  5157                              <1> ;	or	di, di
  5158                              <1> ;	jnz	short sup1
  5159                              <1> ;	inc	di
  5160                              <1> ;       jmp     short SUP0
  5161                              <1> ;sup1:
  5162                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5163                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5164                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5165                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5166                              <1> ;	;POP	DI
  5167                              <1> ;	POP	eDX
  5168                              <1> ;	;POP	CX
  5169                              <1> ;	;POP	BX
  5170                              <1> ;	;POP	AX
  5171                              <1> ;	RETn
  5172                              <1> 
  5173                              <1> ;//////////////////////////////////////////////////////
  5174                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5175                              <1> ;
  5176                              <1> 
  5177                              <1> int13h: ; 21/02/2015
  5178 00002756 9C                  <1> 	pushfd
  5179 00002757 0E                  <1> 	push 	cs
  5180 00002758 E858000000          <1> 	call 	DISK_IO
  5181 0000275D C3                  <1> 	retn
  5182                              <1> 
  5183                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5184                              <1> ;/////////////////////////////////////////////////////////////////////
  5185                              <1> 
  5186                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5187                              <1> ; 23/02/2015
  5188                              <1> ; 21/02/2015 (unix386.s)
  5189                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5190                              <1> ;
  5191                              <1> ; Original Source Code:
  5192                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5193                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5194                              <1> ;
  5195                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5196                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5197                              <1> ;
  5198                              <1> 
  5199                              <1> ;The wait for controller to be not busy is 10 seconds.
  5200                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5201                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5202                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5203                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5204                              <1> 
  5205                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5206                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5207                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5208                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5209                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5210                              <1> 
  5211                              <1> ;The wait for Data request on read and write longs is
  5212                              <1> ;2000 us. (?)
  5213                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5214                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5215                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5216                              <1> 
  5217                              <1> ; Port 61h (PORT_B)
  5218                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5219                              <1> 
  5220                              <1> ; 23/12/2014
  5221                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5222                              <1> 
  5223                              <1> ;--- INT 13H -------------------------------------------------------------------
  5224                              <1> ;									       :
  5225                              <1> ; FIXED DISK I/O INTERFACE						       :
  5226                              <1> ;									       :
  5227                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5228                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5229                              <1> ;									       :
  5230                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5231                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5232                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5233                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5234                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5235                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5236                              <1> ;									       :
  5237                              <1> ;------------------------------------------------------------------------------:
  5238                              <1> ;									       :
  5239                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5240                              <1> ;									       :
  5241                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5242                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5243                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5244                              <1> ;			  DL > 80H - DISK				       :
  5245                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5246                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5247                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5248                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5249                              <1> ;	(AH)= 06H  UNUSED						       :
  5250                              <1> ;	(AH)= 07H  UNUSED						       :
  5251                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5252                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5253                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5254                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5255                              <1> ;	(AH)= 0AH  READ LONG						       :
  5256                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5257                              <1> ;	(AH)= 0CH  SEEK 						       :
  5258                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5259                              <1> ;	(AH)= 0EH  UNUSED						       :
  5260                              <1> ;	(AH)= 0FH  UNUSED						       :
  5261                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5262                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5263                              <1> ;	(AH)= 12H  UNUSED						       :
  5264                              <1> ;	(AH)= 13H  UNUSED						       :
  5265                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5266                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5267                              <1> ;									       :
  5268                              <1> ;-------------------------------------------------------------------------------
  5269                              <1> ;									       :
  5270                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5271                              <1> ;									       :
  5272                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5273                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5274                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5275                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5276                              <1> ;									       :
  5277                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5278                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5279                              <1> ;				 (10 BITS TOTAL)			       :
  5280                              <1> ;									       :
  5281                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5282                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5283                              <1> ;									       :
  5284                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5285                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5286                              <1> ;									       :
  5287                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5288                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5289                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5290                              <1> ;			       80H FOR A BAD SECTOR			       :
  5291                              <1> ;			   N = SECTOR NUMBER				       :
  5292                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5293                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5294                              <1> ;									       :
  5295                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5296                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5297                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5298                              <1> ;									       :
  5299                              <1> ;-------------------------------------------------------------------------------
  5300                              <1> 
  5301                              <1> ;-------------------------------------------------------------------------------
  5302                              <1> ; OUTPUT								       :
  5303                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5304                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5305                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5306                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5307                              <1> ;									       :
  5308                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5309                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5310                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5311                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5312                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5313                              <1> ;		REWRITTEN.						       :
  5314                              <1> ;									       :
  5315                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5316                              <1> ;	   INPUT:							       :
  5317                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5318                              <1> ;	   OUTPUT:							       :
  5319                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5320                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5321                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5322                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5323                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5324                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5325                              <1> ;									       :
  5326                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5327                              <1> ;									       :
  5328                              <1> ;	AH = 0 - NOT PRESENT						       :
  5329                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5330                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5331                              <1> ;	     3 - FIXED DISK						       :
  5332                              <1> ;									       :
  5333                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5334                              <1> ;									       :
  5335                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5336                              <1> ;	INFORMATION.							       :
  5337                              <1> ;									       :
  5338                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5339                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5340                              <1> ;									       :
  5341                              <1> ;-------------------------------------------------------------------------------
  5342                              <1> 
  5343                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5344                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5345                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5346                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5347                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5348                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5349                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5350                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5351                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5352                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5353                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5354                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5355                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5356                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5357                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5358                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5359                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5360                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5361                              <1> 
  5362                              <1> ;--------------------------------------------------------
  5363                              <1> ;							:
  5364                              <1> ; FIXED DISK PARAMETER TABLE				:
  5365                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5366                              <1> ;							:
  5367                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5368                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5369                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5370                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5371                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5372                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5373                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5374                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5375                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5376                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5377                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5378                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5379                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5380                              <1> ;							:
  5381                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5382                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5383                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5384                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5385                              <1> ;							:
  5386                              <1> ;--------------------------------------------------------
  5387                              <1> 
  5388                              <1> ;--------------------------------------------------------
  5389                              <1> ;							:
  5390                              <1> ; HARDWARE SPECIFIC VALUES				:
  5391                              <1> ;							:
  5392                              <1> ;  -  CONTROLLER I/O PORT				:
  5393                              <1> ;							:
  5394                              <1> ;     > WHEN READ FROM: 				:
  5395                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5396                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5397                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5398                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5399                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5400                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5401                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5402                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5403                              <1> ;							:
  5404                              <1> ;     > WHEN WRITTEN TO:				:
  5405                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5406                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5407                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5408                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5409                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5410                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5411                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5412                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5413                              <1> ;							:
  5414                              <1> ;--------------------------------------------------------
  5415                              <1> 
  5416                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5417                              <1> ;HF1_PORT	equ	0170h	
  5418                              <1> ;HF_REG_PORT	EQU	03F6H
  5419                              <1> ;HF1_REG_PORT	equ	0376h
  5420                              <1> 
  5421                              <1> HDC1_BASEPORT	equ	1F0h
  5422                              <1> HDC2_BASEPORT	equ	170h		
  5423                              <1> 
  5424                              <1> align 2
  5425                              <1> 
  5426                              <1> ;-----		STATUS REGISTER
  5427                              <1> 
  5428                              <1> ST_ERROR	EQU	00000001B	;
  5429                              <1> ST_INDEX	EQU	00000010B	;
  5430                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5431                              <1> ST_DRQ		EQU	00001000B	;
  5432                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5433                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5434                              <1> ST_READY	EQU	01000000B	;
  5435                              <1> ST_BUSY 	EQU	10000000B	;
  5436                              <1> 
  5437                              <1> ;-----		ERROR REGISTER
  5438                              <1> 
  5439                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5440                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5441                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5442                              <1> ;		EQU	00001000B	; NOT USED
  5443                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5444                              <1> ;		EQU	00100000B	; NOT USED
  5445                              <1> ERR_DATA_ECC	EQU	01000000B
  5446                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5447                              <1> 
  5448                              <1> 
  5449                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5450                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5451                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5452                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5453                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5454                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5455                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5456                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5457                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5458                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5459                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5460                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5461                              <1> 
  5462                              <1> ;MAX_FILE	EQU	2
  5463                              <1> ;S_MAX_FILE	EQU	2
  5464                              <1> MAX_FILE	equ	4		; 22/12/2014
  5465                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5466                              <1> 
  5467                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5468                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5469                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5470                              <1> 
  5471                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5472                              <1> 
  5473                              <1> ;-----		COMMAND BLOCK REFERENCE
  5474                              <1> 
  5475                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5476                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5477                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5478                              <1> ; 19/12/2014
  5479                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5480                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5481                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5482                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5483                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5484                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5485                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5486                              <1> 
  5487                              <1> align 2
  5488                              <1> 
  5489                              <1> ;----------------------------------------------------------------
  5490                              <1> ; FIXED DISK I/O SETUP						:
  5491                              <1> ;								:
  5492                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5493                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5494                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5495                              <1> ;								:
  5496                              <1> ;----------------------------------------------------------------
  5497                              <1> 
  5498                              <1> DISK_SETUP:
  5499                              <1> 	;CLI
  5500                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5501                              <1> 	;xor	ax,ax
  5502                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5503                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5504                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5505                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5506                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5507                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5508                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5509                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5510                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5511                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5512                              <1> 	;;MOV	[HDISK_INT+2],CS
  5513                              <1> 	;mov	[HDISK_INT1+2],CS
  5514                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5515                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5516                              <1> 	;mov	[HDISK_INT2+2],CS
  5517                              <1> 	;
  5518                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5519                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5520                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5521                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5522                              <1> 	;push	cs
  5523                              <1> 	;pop	ds
  5524                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5525                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5526 0000275E C705[D4700000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5526 00002766 0900                <1>
  5527                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5528                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5529 00002768 C705[D8700000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5529 00002770 0900                <1>
  5530                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5531                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5532 00002772 C705[DC700000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5532 0000277A 0900                <1>
  5533                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5534                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5535 0000277C C705[E0700000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5535 00002784 0900                <1>
  5536                              <1> 	;
  5537                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5538                              <1> 	;;;AND	AL,0BFH
  5539                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5540                              <1> 	;;;JMP	$+2
  5541                              <1> 	;;IODELAY
  5542                              <1> 	;;OUT	INTB01,AL
  5543                              <1> 	;;IODELAY
  5544                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5545                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5546                              <1> 	;;;JMP	$+2
  5547                              <1> 	;;IODELAY
  5548                              <1> 	;;OUT	INTA01,AL
  5549                              <1> 	;
  5550                              <1> 	;STI
  5551                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5552                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5553                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5554                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5555                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5556                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5557                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5558                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5559                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5560                              <1> 	;mov	si, hd0_type
  5561 00002786 BE[306B0000]        <1> 	mov	esi, hd0_type
  5562                              <1> 	;mov	cx, 4
  5563 0000278B B904000000          <1> 	mov	ecx, 4
  5564                              <1> hde_l:
  5565 00002790 AC                  <1> 	lodsb
  5566 00002791 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5567 00002793 7206                <1> 	jb	short _L4
  5568 00002795 FE05[D0700000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5569                              <1> _L4: ; 26/02/2015
  5570 0000279B E2F3                <1> 	loop	hde_l	
  5571                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5572                              <1> ;L4:
  5573                              <1> 	; 
  5574                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5575                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5576                              <1> 	;;mov 	cl, 3
  5577                              <1> 	;;
  5578                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5579                              <1> ;;hdc_dl:
  5580                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5581                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5582                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5583                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5584                              <1> 	;;jnc	short hdc_reset0
  5585                              <1> 	;;loop	hdc_dl
  5586                              <1> 	;;; 27/12/2014
  5587                              <1> 	;;stc
  5588                              <1> 	;;retn
  5589                              <1> 	;
  5590                              <1> ;;hdc_reset0:
  5591                              <1> 	; 18/01/2015
  5592 0000279D 8A0D[D0700000]      <1> 	mov	cl, [HF_NUM]
  5593 000027A3 20C9                <1> 	and	cl, cl
  5594 000027A5 740D                <1> 	jz	short POD_DONE
  5595                              <1> 	;
  5596 000027A7 B27F                <1> 	mov	dl, 7Fh
  5597                              <1> hdc_reset1:
  5598 000027A9 FEC2                <1> 	inc	dl
  5599                              <1> 	;; 31/12/2015
  5600                              <1> 	;;push	dx
  5601                              <1> 	;;push	cx
  5602                              <1> 	;;push	ds
  5603                              <1> 	;;sub	ax, ax
  5604                              <1> 	;;mov	ds, ax
  5605                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5606                              <1> 	;;pop	ds
  5607                              <1> 	;;MOV	BX,AX
  5608                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5609                              <1> 	;;MOV	CX,AX
  5610                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5611                              <1> 	;;
  5612                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5613                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5614                              <1> 	;;pop	cx
  5615                              <1> 	;;pop	dx
  5616                              <1> 	;;
  5617                              <1> 	; 18/01/2015
  5618 000027AB B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5619                              <1> 	;int	13h
  5620 000027AD E8A4FFFFFF          <1> 	call	int13h
  5621 000027B2 E2F5                <1> 	loop	hdc_reset1
  5622                              <1> POD_DONE:
  5623 000027B4 C3                  <1> 	RETn
  5624                              <1> 
  5625                              <1> ;;-----	POD_ERROR
  5626                              <1> 
  5627                              <1> ;;CTL_ERRX:
  5628                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5629                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5630                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5631                              <1> ;	;JMP	short POD_DONE
  5632                              <1> 
  5633                              <1> ;;HD_RESET_1:
  5634                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5635                              <1> ;;	;PUSH	CX
  5636                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5637                              <1> ;;	INT	13H
  5638                              <1> ;;	JC	short RES_2
  5639                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5640                              <1> ;;	INT	13H
  5641                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5642                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5643                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5644                              <1> ;;					; (30 seconds)		
  5645                              <1> ;;	;cmc
  5646                              <1> ;;	;JNC	short RES_1
  5647                              <1> ;;	jb	short RES_1
  5648                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5649                              <1> ;;	;TEST	DL,1
  5650                              <1> ;;	;JNZ	RES_E1
  5651                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5652                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5653                              <1> ;;	;JMP	SHORT RES_E1
  5654                              <1> ;;RES_ER: ; 22/12/2014
  5655                              <1> ;;RES_OK:
  5656                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5657                              <1> ;;	;POP	BX
  5658                              <1> ;;	RETn
  5659                              <1> ;;
  5660                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5661                              <1> ;;	INT	13H
  5662                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5663                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5664                              <1> ;;	INT	13H
  5665                              <1> ;;	JC	short RES_ER
  5666                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5667                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5668                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5669                              <1> ;;	INT	13H
  5670                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5671                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5672                              <1> ;;	JE	short RES_OK
  5673                              <1> ;;	CMP	AH,DATA_CORRECTED
  5674                              <1> ;;	JE	short RES_OK
  5675                              <1> ;;	CMP	AH,BAD_ECC
  5676                              <1> ;;	JE	short RES_OK
  5677                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5678                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5679                              <1> ;;					; (60 seconds)		
  5680                              <1> ;;	cmc
  5681                              <1> ;;	JC	short RES_ER		; FAILED
  5682                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5683                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5684                              <1> ;;	AND	AL,3FH
  5685                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5686                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5687                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5688                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5689                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5690                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5691                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5692                              <1> ;;	;TEST	DL,1
  5693                              <1> ;;	;JNZ	short RES_E1
  5694                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5695                              <1> ;;;RES_E1:
  5696                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5697                              <1> ;;;RES_OK:
  5698                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5699                              <1> ;;	;POP	BX
  5700                              <1> ;;	;RETn
  5701                              <1> ;
  5702                              <1> ;;SET_FAIL:
  5703                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5704                              <1> ;	;CALL	CMOS_READ
  5705                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5706                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5707                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5708                              <1> ;	;RETn
  5709                              <1> ;
  5710                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5711                              <1> ;	;POP	AX			; SAVE RETURN
  5712                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5713                              <1> ;	;POP	BX
  5714                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5715                              <1> ;	;PUSH	CX
  5716                              <1> ;	;PUSH	AX
  5717                              <1> ;	;push	ds
  5718                              <1> ;	;xor	ax, ax
  5719                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5720                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5721                              <1> ;	;				; BX = START TIME
  5722                              <1> ;	;				; CX = END TIME
  5723                              <1> ;	;pop	ds
  5724                              <1> ;	;CMP	BX,CX
  5725                              <1> ;	;JB	short TCHK1		; START < END
  5726                              <1> ;	;CMP	BX,AX
  5727                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5728                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5729                              <1> ;;TCHK1: CMP	AX,BX
  5730                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5731                              <1> ;;TCHK2: CMP	AX,CX
  5732                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5733                              <1> ;;					; OR CURRENT < END < START
  5734                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5735                              <1> ;;	RETn
  5736                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5737                              <1> ;;	RETn
  5738                              <1> ;;
  5739                              <1> ;;int_13h:
  5740                              <1> 
  5741                              <1> ;----------------------------------------
  5742                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5743                              <1> ;----------------------------------------
  5744                              <1> 
  5745                              <1> DISK_IO:
  5746 000027B5 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5747                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5748                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5749                              <1> 	;;call	int40h
  5750                              <1> 	;jb	DISKETTE_IO_1
  5751                              <1> 	; 05/12/2021
  5752 000027B8 7305                <1> 	jnb	short A1
  5753 000027BA E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5754                              <1> ;RET_2:
  5755                              <1> 	;RETf	2			; BACK TO CALLER
  5756                              <1> ;	retf	4
  5757                              <1> A1:
  5758 000027BF FB                  <1> 	STI				; ENABLE INTERRUPTS
  5759                              <1> 	;; 04/01/2015
  5760                              <1> 	;;OR	AH,AH
  5761                              <1> 	;;JNZ	short A2
  5762                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5763                              <1> 	;;SUB	AH,AH
  5764 000027C0 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5765 000027C3 772E                <1> 	JA	short RET_2
  5766                              <1> 	; 18/01/2015
  5767 000027C5 08E4                <1> 	or	ah,ah
  5768 000027C7 742D                <1> 	jz	short A4
  5769 000027C9 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5770 000027CC 7504                <1> 	jne	short A2
  5771 000027CE 28E4                <1> 	sub	ah,ah	; Reset
  5772 000027D0 EB24                <1> 	jmp	short A4
  5773                              <1> A2:
  5774 000027D2 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5775                              <1> 	;JNZ	short A3
  5776                              <1>         ;JMP    GET_PARM_N
  5777                              <1> 	;je	GET_PARM_N
  5778                              <1> 	; 05/12/2021
  5779 000027D5 7505                <1> 	jne	short A3
  5780 000027D7 E90D030000          <1> 	jmp	GET_PARM_N
  5781                              <1> A3:	
  5782 000027DC 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5783                              <1> 	;JNZ	short A4
  5784                              <1>         ;JMP    READ_DASD_TYPE
  5785                              <1> 	;je	READ_DASD_TYPE
  5786                              <1> 	; 05/12/2021
  5787 000027DF 7505                <1> 	jne	short A3_A4
  5788 000027E1 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5789                              <1> A3_A4:
  5790                              <1> 	; 02/02/2015
  5791 000027E6 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5792                              <1> 	; 12/01/2015
  5793 000027E9 F5                  <1> 	cmc
  5794 000027EA 730A                <1> 	jnc	short A4
  5795                              <1> 	; 30/01/2015
  5796                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5797 000027EC C605[CF700000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5798                              <1> 	;jmp	short RET_2
  5799                              <1> RET_2:
  5800 000027F3 CA0400              <1> 	retf	4
  5801                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5802 000027F6 C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5803 000027FA 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5804 000027FB 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5805 000027FC 52                  <1> 	PUSH	eDX
  5806 000027FD 1E                  <1> 	PUSH	DS
  5807 000027FE 06                  <1> 	PUSH	ES
  5808 000027FF 56                  <1> 	PUSH	eSI
  5809 00002800 57                  <1> 	PUSH	eDI
  5810                              <1> 	;;04/01/2015
  5811                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5812                              <1> 	;;JNZ	short A5
  5813                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5814                              <1> ;;A5:	
  5815                              <1> 	;push	cs
  5816                              <1> 	;pop	ds
  5817                              <1> 	; 21/02/2015
  5818                              <1> 	;push	ax
  5819                              <1> 	; 05/12/2021
  5820 00002801 50                  <1> 	push	eax
  5821 00002802 66B81000            <1> 	mov	ax, KDATA
  5822 00002806 8ED8                <1> 	mov	ds, ax
  5823 00002808 8EC0                <1> 	mov	es, ax	
  5824                              <1> 	;pop	ax
  5825                              <1> 	; 05/12/2021
  5826 0000280A 58                  <1> 	pop	eax
  5827 0000280B E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5828                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5829 00002810 8A25[CF700000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5830 00002816 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5831 00002819 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5832 0000281A 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5833 0000281B 5E                  <1> 	POP	eSI
  5834 0000281C 07                  <1>         POP     ES
  5835 0000281D 1F                  <1>         POP     DS
  5836 0000281E 5A                  <1> 	POP	eDX
  5837 0000281F 59                  <1> 	POP	eCX
  5838 00002820 5B                  <1> 	POP	eBX
  5839 00002821 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5840                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5841 00002822 CA0400              <1> 	retf	4
  5842                              <1> ; 21/02/2015
  5843                              <1> ;       dw --> dd
  5844                              <1> M1:					; FUNCTION TRANSFER TABLE
  5845 00002825 [DE290000]          <1> 	dd	DISK_RESET		; 000H
  5846 00002829 [532A0000]          <1> 	dd	RETURN_STATUS		; 001H
  5847 0000282D [602A0000]          <1> 	dd	DISK_READ		; 002H
  5848 00002831 [692A0000]          <1> 	dd	DISK_WRITE		; 003H
  5849 00002835 [722A0000]          <1> 	dd	DISK_VERF		; 004H
  5850 00002839 [8A2A0000]          <1> 	dd	FMT_TRK 		; 005H
  5851 0000283D [D4290000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5852 00002841 [D4290000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5853 00002845 [D4290000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5854 00002849 [4B2B0000]          <1> 	dd	INIT_DRV		; 009H
  5855 0000284D [AA2B0000]          <1> 	dd	RD_LONG 		; 00AH
  5856 00002851 [B32B0000]          <1> 	dd	WR_LONG 		; 00BH
  5857 00002855 [BC2B0000]          <1> 	dd	DISK_SEEK		; 00CH
  5858 00002859 [DE290000]          <1> 	dd	DISK_RESET		; 00DH
  5859 0000285D [D4290000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5860 00002861 [D4290000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5861 00002865 [E42B0000]          <1> 	dd	TST_RDY 		; 010H
  5862 00002869 [082C0000]          <1> 	dd	HDISK_RECAL		; 011H
  5863 0000286D [D4290000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5864 00002871 [D4290000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5865 00002875 [3E2C0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5866                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5867 00002879 [D4290000]          <1> 	dd	BAD_COMMAND		; 015h
  5868 0000287D [D4290000]          <1> 	dd	BAD_COMMAND		; 016h
  5869 00002881 [D4290000]          <1> 	dd	BAD_COMMAND		; 017h
  5870 00002885 [D4290000]          <1> 	dd	BAD_COMMAND		; 018h
  5871 00002889 [D4290000]          <1> 	dd	BAD_COMMAND		; 019h
  5872 0000288D [D4290000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5873 00002891 [602A0000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5874 00002895 [692A0000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5875                              <1> M1L     EQU    $-M1
  5876                              <1> 
  5877                              <1> DISK_IO_CONT:
  5878                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5879 00002899 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5880                              <1> 	;;JNZ	short SU0
  5881                              <1>         ;;JMP	RETURN_STATUS
  5882                              <1> 	;je	RETURN_STATUS
  5883                              <1> 	; 05/12/2021
  5884 0000289C 7505                <1> 	jne	short SU0
  5885 0000289E E9B0010000          <1> 	jmp	RETURN_STATUS
  5886                              <1> SU0:
  5887 000028A3 C605[CF700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5888                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5889                              <1> 	;mov	si, bx ;; 14/02/2015
  5890 000028AA 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5891 000028AC 8A1D[D0700000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5892                              <1> 	;; 04/01/2015
  5893                              <1> 	;;PUSH	AX
  5894 000028B2 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5895                              <1> 					; (get drive number as 0 to 3)
  5896 000028B5 38D3                <1> 	CMP	BL,DL
  5897                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5898                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5899                              <1> 	; 05/12/2021
  5900 000028B7 7705                <1> 	ja	short su0_su1
  5901 000028B9 E916010000          <1> 	jmp	BAD_COMMAND
  5902                              <1> su0_su1:
  5903                              <1>         ;;03/01/2015
  5904 000028BE 29DB                <1> 	sub	ebx, ebx
  5905 000028C0 88D3                <1> 	mov	bl, dl
  5906                              <1> 	;sub	bh, bh
  5907 000028C2 883D[E4700000]      <1> 	mov	[LBAMode], bh 	; 0
  5908                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5909                              <1> 	;test	byte [ebx+hd0_type], 1
  5910                              <1> 	;jz	short su1		; no
  5911                              <1> 	;inc	byte [LBAMode]
  5912                              <1> ;su1:
  5913                              <1> 	; 21/02/2015 (32 bit modification)
  5914                              <1> 	; 04/01/2015
  5915                              <1> 	;push	ax ; ***
  5916                              <1> 	; 05/12/2021
  5917 000028C8 50                  <1> 	push	eax ; ***
  5918                              <1> 	;PUSH	ES ; **
  5919                              <1> 	;PUSH	DX ; *
  5920                              <1> 	; 05/12/2021
  5921 000028C9 52                  <1> 	push	edx ; *
  5922                              <1> 	;push	ax
  5923 000028CA 50                  <1> 	push	eax
  5924 000028CB E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5925                              <1> 	; 02/02/2015
  5926                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5927 000028D0 668B4310            <1> 	mov	ax, [ebx+16]
  5928 000028D4 66A3[246B0000]      <1> 	mov	[HF_PORT], ax
  5929                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  5930 000028DA 668B5312            <1> 	mov	dx, [ebx+18]
  5931 000028DE 668915[266B0000]    <1> 	mov	[HF_REG_PORT], dx
  5932                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  5933 000028E5 8A4314              <1> 	mov	al, [ebx+20]
  5934                              <1> 	; 23/02/2015
  5935 000028E8 A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  5936 000028EA 7406                <1> 	jz 	short su1
  5937 000028EC FE05[E4700000]      <1> 	inc	byte [LBAMode] ; 1 
  5938                              <1> su1: 	 
  5939 000028F2 C0E804              <1> 	shr 	al, 4
  5940 000028F5 2401                <1> 	and	al, 1			
  5941 000028F7 A2[286B0000]        <1> 	mov	[hf_m_s], al 
  5942                              <1> 	;
  5943                              <1> 	; 03/01/2015
  5944                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  5945 000028FC 8A4308              <1> 	mov	al, [ebx+8]
  5946                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  5947 000028FF EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  5948                              <1> 					; Control Byte:  (= 08h, here)
  5949                              <1> 					; bit 0 - 0
  5950                              <1> 					; bit 1 - nIEN (1 = disable irq)
  5951                              <1> 					; bit 2 - SRST (software RESET)
  5952                              <1> 					; bit 3 - use extra heads (8 to 15)
  5953                              <1> 					;         -always set to 1-	
  5954                              <1> 					; (bits 3 to 7 are reserved
  5955                              <1> 					;          for ATA devices)
  5956 00002900 8A25[D1700000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  5957 00002906 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  5958 00002909 08C4                <1> 	OR	AH,AL
  5959 0000290B 8825[D1700000]      <1> 	MOV	[CONTROL_BYTE],AH	
  5960                              <1> 	; 04/01/2015
  5961                              <1> 	;pop	ax
  5962                              <1> 	; 05/12/2021
  5963 00002911 58                  <1> 	pop	eax
  5964                              <1> 	;pop	dx ; * ;; 14/02/2015
  5965                              <1> 	; 05/12/2021
  5966 00002912 5A                  <1> 	pop	edx ; *
  5967 00002913 20E4                <1> 	and	ah, ah	; Reset function ?
  5968 00002915 7506                <1> 	jnz	short su2
  5969                              <1> 	;;pop	dx ; * ;; 14/02/2015
  5970                              <1> 	;pop	es ; **
  5971                              <1> 	;pop	ax ; ***
  5972                              <1> 	; 05/12/2021
  5973 00002917 58                  <1> 	pop	eax ; ***	
  5974                              <1> 	;;pop	bx
  5975 00002918 E9C1000000          <1>         jmp     DISK_RESET
  5976                              <1> su2:
  5977 0000291D 803D[E4700000]00    <1> 	cmp	byte [LBAMode], 0
  5978 00002924 765E                <1> 	jna	short su3
  5979                              <1> 	;
  5980                              <1> 	; 02/02/2015 (LBA read/write function calls)
  5981 00002926 80FC1B              <1> 	cmp	ah, 1Bh
  5982 00002929 720B                <1> 	jb	short lbarw1
  5983 0000292B 80FC1C              <1> 	cmp	ah, 1Ch
  5984 0000292E 7759                <1> 	ja 	short invldfnc
  5985                              <1> 	;;pop	dx ; * ; 14/02/2015
  5986                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  5987 00002930 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  5988                              <1> 	;; 14/02/2015
  5989 00002932 88D1                <1> 	mov	cl, dl ; 14/02/2015
  5990                              <1> 	;;mov	dx, bx
  5991                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  5992                              <1> 	;;mov	bx, di
  5993                              <1> 	;mov	si, di ; Buffer offset
  5994 00002934 EB2E                <1> 	jmp	short lbarw2
  5995                              <1> lbarw1:
  5996                              <1> 	; convert CHS to LBA
  5997                              <1> 	;
  5998                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  5999                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6000                              <1> 	;	+ Sector - 1
  6001                              <1> 	;push	dx ; * ;; 14/02/2015
  6002                              <1> 	; 05/12/2021
  6003 00002936 52                  <1> 	push	edx ; *
  6004                              <1> 	;xor	dh, dh
  6005 00002937 31D2                <1> 	xor	edx, edx
  6006                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6007 00002939 8A530E              <1> 	mov	dl, [ebx+14]
  6008                              <1> 	;xor	ah, ah
  6009 0000293C 31C0                <1> 	xor	eax, eax
  6010                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6011 0000293E 8A4302              <1> 	mov	al, [ebx+2]
  6012 00002941 FEC8                <1> 	dec	al
  6013                              <1> 	;inc	ax		; 0 =  256
  6014 00002943 40                  <1> 	inc	eax ; 05/12/2021
  6015 00002944 66F7E2              <1> 	mul 	dx
  6016                              <1> 		; AX = # of Heads" * Sectors/Track
  6017 00002947 6689CA              <1> 	mov	dx, cx
  6018                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6019 0000294A 83E13F              <1> 	and	ecx, 3fh
  6020 0000294D 86D6                <1> 	xchg	dl, dh
  6021 0000294F C0EE06              <1> 	shr	dh, 6
  6022                              <1> 		; DX = cylinder (0 to 1023)
  6023                              <1> 	;mul 	dx
  6024                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6025 00002952 F7E2                <1> 	mul	edx
  6026 00002954 FEC9                <1> 	dec	cl  ; sector - 1
  6027                              <1> 	;add	ax, cx
  6028                              <1> 	;adc	dx, 0
  6029                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6030 00002956 01C8                <1> 	add	eax, ecx
  6031                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6032                              <1> 	; 05/12/2021
  6033 00002958 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6034                              <1> 	;push	dx
  6035                              <1> 	;push	ax
  6036 00002959 50                  <1> 	push	eax
  6037                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6038 0000295A 8A430E              <1> 	mov	al, [ebx+14]
  6039 0000295D F6E5                <1> 	mul	ch
  6040                              <1> 		; AX = Head * Sectors/Track
  6041 0000295F 6699                <1>         cwd
  6042                              <1> 	;pop	dx
  6043 00002961 5A                  <1> 	pop	edx
  6044                              <1> 	;add	ax, dx
  6045                              <1> 	;pop	dx
  6046                              <1> 	;adc	dx, 0 ; add carry bit
  6047 00002962 01D0                <1> 	add	eax, edx
  6048                              <1> lbarw2:
  6049 00002964 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6050 00002966 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6051 00002968 C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6052                              <1> 				; NOTE: Features register (1F1h, 171h)
  6053                              <1> 				; is not used for ATA device R/W functions. 
  6054                              <1> 				; It is old/obsolete 'write precompensation'
  6055                              <1> 				; register and error register
  6056                              <1> 				; for old ATA/IDE devices.
  6057                              <1> 	; 18/01/2014
  6058                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6059 0000296C 8A0D[286B0000]      <1> 	mov	cl, [hf_m_s]
  6060                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6061                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6062                              <1> 				; bit 6 = 1 = LBA mode
  6063                              <1> 				; bit 7 = 1
  6064 00002972 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6065                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6066 00002975 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6067 0000297A C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6068                              <1> 	;or	dh, ch
  6069 0000297D 09C8                <1> 	or	eax, ecx	
  6070                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6071                              <1> 				  ; (Sector Number Register)
  6072                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6073                              <1> 				  ; (Cylinder Low Register)
  6074                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6075                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6076                              <1> 				  ; (Cylinder High Register)
  6077                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6078                              <1> 				  ; (Drive/Head Register)
  6079                              <1> 	
  6080                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6081 0000297F 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6082                              <1> 	;14/02/2015
  6083                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6084 00002982 EB37                <1> 	jmp	short su4
  6085                              <1> su3:
  6086                              <1> 	; 02/02/2015 
  6087                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6088 00002984 80FC14              <1> 	cmp 	ah, 14h
  6089 00002987 7603                <1> 	jna 	short chsfnc
  6090                              <1> invldfnc:
  6091                              <1>         ; 14/02/2015  
  6092                              <1> 	;pop	es ; **
  6093                              <1>         ;pop	ax ; ***
  6094                              <1>         ; 05/12/2021
  6095 00002989 58                  <1> 	pop	eax ; ***
  6096                              <1> 	;jmp	short BAD_COMMAND_POP
  6097 0000298A EB48                <1>         jmp     short BAD_COMMAND
  6098                              <1> chsfnc:	
  6099                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6100 0000298C 668B4305            <1> 	mov	ax, [ebx+5]
  6101 00002990 66C1E802            <1> 	SHR	AX,2
  6102 00002994 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6103                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6104                              <1> 	;;PUSH	DX
  6105                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6106                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6107                              <1> 	;;POP	DX ; * 
  6108                              <1> 	;;POP	ES ; **
  6109                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6110                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6111                              <1> 	;;OR	AH,AL
  6112                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6113                              <1> 	;
  6114 00002997 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6115 00002999 243F                <1> 	AND	AL,3FH
  6116 0000299B 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6117 0000299E 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6118 000029A1 88C8                <1> 	MOV	AL,CL
  6119 000029A3 C0E806              <1> 	SHR	AL,6
  6120 000029A6 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6121                              <1> 	;;05/01/2015
  6122                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6123 000029A9 A0[286B0000]        <1> 	mov	al, [hf_m_s]
  6124 000029AE C0E004              <1> 	SHL	AL,4
  6125 000029B1 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6126 000029B4 08F0                <1> 	OR	AL,DH
  6127                              <1> 	;OR	AL,80H or 20H
  6128 000029B6 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6129 000029B8 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6130                              <1> su4:
  6131                              <1> 	;POP	ES ; **
  6132                              <1>         ;; 14/02/2015
  6133                              <1>         ;;POP   AX
  6134                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6135                              <1>         ;;PUSH  AX
  6136                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6137                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6138                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6139                              <1> 	;pop     ax ; ***
  6140                              <1> 	; 05/12/2021
  6141 000029BB 58                  <1> 	pop	eax ; ***
  6142 000029BC 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6143 000029BF 29DB                <1>         sub	ebx, ebx
  6144 000029C1 88E3                <1> 	mov     bl, ah
  6145                              <1>         ;xor	bh, bh
  6146                              <1>         ;sal	bx, 1
  6147 000029C3 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6148                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6149                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6150                              <1>         ;;JNB   short BAD_COMMAND_POP
  6151                              <1>         ;cmp	bx, M1L
  6152 000029C7 83FB74              <1> 	cmp	ebx, M1L
  6153 000029CA 7308                <1> 	jnb	short BAD_COMMAND
  6154                              <1>         ;xchg	bx, si
  6155 000029CC 87DE                <1>         xchg	ebx, esi
  6156                              <1> 	;;;POP	AX			; RESTORE AX
  6157                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6158                              <1> 	
  6159                              <1> 	;;PUSH	CX
  6160                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6161                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6162                              <1> 	;SHR	CX,4
  6163                              <1> 	;MOV	AX,ES
  6164                              <1> 	;ADD	AX,CX
  6165                              <1> 	;MOV	ES,AX
  6166                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6167                              <1> 	;;POP	AX
  6168                              <1> 	;;POP	CX
  6169                              <1> 	;;JMP	word [CS:SI+M1]
  6170                              <1> 	;jmp	word [SI+M1]
  6171 000029CE FFA6[25280000]      <1> 	jmp	dword [esi+M1]
  6172                              <1> ;;BAD_COMMAND_POP:
  6173                              <1> ;;	POP	AX
  6174                              <1> ;;	POP	BX
  6175                              <1> BAD_COMMAND:
  6176 000029D4 C605[CF700000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6177 000029DB B000                <1> 	MOV	AL,0
  6178 000029DD C3                  <1> 	RETn
  6179                              <1> 
  6180                              <1> ;----------------------------------------
  6181                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6182                              <1> ;----------------------------------------
  6183                              <1> 
  6184                              <1> ; 18-1-2015 : one controller reset (not other one)
  6185                              <1> 
  6186                              <1> DISK_RESET:
  6187 000029DE FA                  <1> 	CLI
  6188 000029DF E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6189                              <1> 	;JMP	$+2
  6190                              <1> 	IODELAY
  2077 000029E1 EB00                <2>  jmp short $+2
  2078 000029E3 EB00                <2>  jmp short $+2
  6191                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6192 000029E5 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6193 000029E7 E6A1                <1> 	OUT	INTB01,AL
  6194 000029E9 FB                  <1> 	STI				; START INTERRUPTS
  6195                              <1> 	; 14/02/2015
  6196                              <1> 	;mov	di, dx
  6197                              <1> 	; 05/12/2021
  6198 000029EA 89D7                <1> 	mov	edi, edx	
  6199                              <1> 	; 04/01/2015
  6200                              <1> 	;xor	di,di
  6201                              <1> drst0:
  6202 000029EC B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6203                              <1> 	;MOV	DX,HF_REG_PORT
  6204 000029EE 668B15[266B0000]    <1> 	MOV	DX,[HF_REG_PORT]
  6205 000029F5 EE                  <1> 	OUT	DX,AL			; RESET
  6206                              <1> ;	MOV	CX,10			; DELAY COUNT
  6207                              <1> ;DRD:	DEC	CX
  6208                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6209                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6210 000029F6 B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6211 000029FB E8CEEBFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6212                              <1>                                         ; 40 micro seconds)
  6213 00002A00 A0[D1700000]        <1> 	mov	al,[CONTROL_BYTE]
  6214 00002A05 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6215 00002A07 EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6216 00002A08 E807040000          <1> 	CALL	NOT_BUSY
  6217 00002A0D 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6218 00002A0F 668B15[246B0000]    <1> 	MOV	DX,[HF_PORT]
  6219 00002A16 FEC2                <1> 	inc	dl  ; HF_PORT+1
  6220                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6221                              <1>         ;mov	cl, 10
  6222 00002A18 B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6223                              <1> drst1:
  6224 00002A1D EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6225 00002A1E 3C01                <1> 	CMP	AL,1
  6226                              <1> 	; 04/01/2015
  6227 00002A20 740A                <1> 	jz	short drst2
  6228                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6229                              <1>         	; Drive/Head Register - bit 4
  6230 00002A22 E2F9                <1> 	loop	drst1
  6231                              <1> DRERR:	
  6232 00002A24 C605[CF700000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6233 00002A2B C3                  <1> 	RETn
  6234                              <1> drst2:
  6235                              <1> 	; 14/02/2015
  6236                              <1> 	;mov	dx, di
  6237                              <1> 	; 05/12/2021
  6238 00002A2C 89FA                <1> 	mov	edx, edi
  6239                              <1> ;drst3:
  6240                              <1> ;	; 05/01/2015
  6241                              <1> ;	shl 	di,1
  6242                              <1> ;	; 04/01/2015
  6243                              <1> ;	mov	ax,[di+hd_cports]
  6244                              <1> ;	cmp	ax,[HF_REG_PORT]
  6245                              <1> ;	je	short drst4
  6246                              <1> ;	mov	[HF_REG_PORT], ax
  6247                              <1> ;	; 03/01/2015
  6248                              <1> ;	mov	ax,[di+hd_ports]
  6249                              <1> ;       mov     [HF_PORT], ax
  6250                              <1> ;	; 05/01/2014
  6251                              <1> ;	shr	di,1
  6252                              <1> ;	; 04/01/2015
  6253                              <1> ;	jmp	short drst0	; reset other controller
  6254                              <1> ;drst4:
  6255                              <1> ;	; 05/01/2015
  6256                              <1> ;	shr	di,1
  6257                              <1> ;	mov	al,[di+hd_dregs]
  6258                              <1> ;	and	al,10h ; bit 4 only
  6259                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6260                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6261                              <1> 	;
  6262 00002A2E A0[286B0000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6263 00002A33 A801                <1> 	test	al,1
  6264                              <1> ;	jnz	short drst6
  6265 00002A35 7516                <1>         jnz     short drst4
  6266 00002A37 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6267                              <1> ;drst5:
  6268                              <1> drst3:
  6269 00002A3B E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6270                              <1> 	;mov	dx,di
  6271 00002A40 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6272                              <1> 	; 04/01/2014
  6273                              <1> ;	inc	di
  6274                              <1> ;	mov	dx,di
  6275                              <1> ;	cmp	dl,[HF_NUM]
  6276                              <1> ;	jb	short drst3
  6277                              <1> ;DRE:
  6278 00002A45 C605[CF700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6279 00002A4C C3                  <1> 	RETn
  6280                              <1> ;drst6:
  6281                              <1> drst4:		; Drive/Head Register - bit 4
  6282 00002A4D 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6283                              <1>         ;jmp    short drst5
  6284 00002A51 EBE8                <1>         jmp     short drst3
  6285                              <1> 
  6286                              <1> ;----------------------------------------
  6287                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6288                              <1> ;----------------------------------------
  6289                              <1> 
  6290                              <1> RETURN_STATUS:
  6291 00002A53 A0[CF700000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6292 00002A58 C605[CF700000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6293 00002A5F C3                  <1> 	RETn
  6294                              <1> 
  6295                              <1> ;----------------------------------------
  6296                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6297                              <1> ;----------------------------------------
  6298                              <1> 
  6299                              <1> DISK_READ:
  6300 00002A60 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6301 00002A64 E92A020000          <1>         JMP     COMMANDI
  6302                              <1> 
  6303                              <1> ;----------------------------------------
  6304                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6305                              <1> ;----------------------------------------
  6306                              <1> 
  6307                              <1> DISK_WRITE:
  6308 00002A69 C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6309 00002A6D E976020000          <1>         JMP     COMMANDO
  6310                              <1> 
  6311                              <1> ;----------------------------------------
  6312                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6313                              <1> ;----------------------------------------
  6314                              <1> 
  6315                              <1> DISK_VERF:
  6316 00002A72 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6317 00002A76 E8E4020000          <1> 	CALL	COMMAND
  6318 00002A7B 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6319 00002A7D E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6320 00002A82 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6321 00002A84 E8E3030000          <1> 	CALL	CHECK_STATUS
  6322                              <1> VERF_EXIT:
  6323 00002A89 C3                  <1> 	RETn
  6324                              <1> 
  6325                              <1> ;----------------------------------------
  6326                              <1> ;	FORMATTING	     (AH = 05H) :
  6327                              <1> ;----------------------------------------
  6328                              <1> 
  6329                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6330 00002A8A C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6331                              <1> 	;PUSH	ES
  6332                              <1> 	;PUSH	BX
  6333 00002A8E 53                  <1> 	push	ebx
  6334 00002A8F E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6335                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6336 00002A94 8A430E              <1> 	mov	al, [ebx+14]
  6337 00002A97 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6338 00002A9A 5B                  <1> 	pop	ebx
  6339                              <1> 	;POP	BX
  6340                              <1> 	;POP	ES
  6341 00002A9B E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6342                              <1> 
  6343                              <1> ;----------------------------------------
  6344                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6345                              <1> ;----------------------------------------
  6346                              <1> 
  6347                              <1> READ_DASD_TYPE:
  6348                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6349 00002AA0 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6350                              <1> 	;PUSH	ES
  6351 00002AA1 53                  <1> 	PUSH	eBX
  6352                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6353                              <1> 	;push	cs
  6354                              <1> 	;pop	ds
  6355 00002AA2 66BB1000            <1>         mov	bx, KDATA
  6356 00002AA6 8EDB                <1> 	mov	ds, bx
  6357                              <1> 	;mov	es, bx
  6358 00002AA8 C605[CF700000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6359 00002AAF 8A1D[D0700000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6360 00002AB5 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6361 00002AB8 38D3                <1> 	CMP	BL,DL
  6362 00002ABA 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6363 00002ABC E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6364                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6365 00002AC1 8A4302              <1> 	mov	al, [ebx+2]
  6366                              <1> 	;MOV	CL,[ES:BX+14]
  6367 00002AC4 8A4B0E              <1> 	mov	cl, [ebx+14]
  6368 00002AC7 F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6369                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6370 00002AC9 668B0B              <1> 	mov	cx, [ebx]
  6371                              <1> 	;
  6372                              <1> 	; 02/01/2015 
  6373                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6374                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6375 00002ACC 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6376                              <1> 	;
  6377 00002ACE 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6378 00002AD1 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6379 00002AD4 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6380                              <1> 	;SUB	AX,AX
  6381 00002AD7 28C0                <1> 	sub	al, al
  6382 00002AD9 B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6383 00002ADB 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6384                              <1> 	;POP	ES
  6385 00002ADC 1F                  <1> 	POP	DS
  6386 00002ADD F8                  <1> 	CLC				; CLEAR CARRY
  6387                              <1> 	;RETf	2
  6388 00002ADE CA0400              <1> 	retf	4
  6389                              <1> RDT_NOT_PRESENT:
  6390                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6391                              <1> 	; 05/12/2021
  6392 00002AE1 29C0                <1> 	sub	eax, eax
  6393                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6394                              <1> 	;MOV	DX,AX
  6395 00002AE3 89C1                <1> 	mov	ecx, eax
  6396 00002AE5 89C2                <1> 	mov	edx, eax
  6397 00002AE7 EBF2                <1> 	JMP	short RDT2
  6398                              <1> 
  6399                              <1> ;----------------------------------------
  6400                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6401                              <1> ;----------------------------------------
  6402                              <1> 
  6403                              <1> GET_PARM_N:
  6404                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6405 00002AE9 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6406                              <1> 	;PUSH	ES
  6407 00002AEA 53                  <1> 	PUSH	eBX
  6408                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6409                              <1> 	;MOV	DS,AX
  6410                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6411                              <1> 	;JZ	short G0
  6412                              <1> 	;LES	BX,@HF1_TBL_VEC
  6413                              <1> 	;JMP	SHORT G1
  6414                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6415                              <1> ;G1:
  6416                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6417                              <1> 	; 22/12/2014
  6418                              <1> 	;push	cs
  6419                              <1> 	;pop	ds
  6420 00002AEB 66BB1000            <1> 	mov	bx, KDATA
  6421 00002AEF 8EDB                <1> 	mov	ds, bx
  6422                              <1> 	;mov	es, bx
  6423                              <1> 	;
  6424 00002AF1 80EA80              <1> 	SUB	DL,80H
  6425 00002AF4 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6426 00002AF7 7340                <1> 	JAE	short G4
  6427                              <1> 	;
  6428 00002AF9 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6429                              <1> 	; 22/12/2014
  6430 00002AFB 88D3                <1> 	mov	bl, dl
  6431                              <1> 	;xor	bh, bh  
  6432 00002AFD C0E302              <1> 	shl	bl, 2			; convert index to offset
  6433                              <1> 	;add	bx, HF_TBL_VEC
  6434 00002B00 81C3[D4700000]      <1> 	add	ebx, HF_TBL_VEC
  6435                              <1> 	;mov	ax, [bx+2]
  6436                              <1> 	;mov	es, ax			; dpt segment
  6437                              <1> 	;mov	bx, [bx]		; dpt offset
  6438 00002B06 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6439                              <1> 
  6440 00002B08 C605[CF700000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6441                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6442 00002B0F 668B03              <1> 	mov	ax, [ebx]
  6443                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6444 00002B12 6648                <1> 	dec	ax			; max. cylinder number
  6445 00002B14 88C5                <1> 	MOV	CH,AL
  6446 00002B16 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6447 00002B1A 66D1E8              <1> 	SHR	AX,1
  6448 00002B1D 66D1E8              <1> 	SHR	AX,1
  6449                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6450 00002B20 0A430E              <1> 	or	al, [ebx+14]
  6451 00002B23 88C1                <1> 	MOV	CL,AL
  6452                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6453 00002B25 8A7302              <1> 	mov	dh, [ebx+2]
  6454 00002B28 FECE                <1> 	DEC	DH			; 0-N RANGE
  6455 00002B2A 8A15[D0700000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6456                              <1> 	;SUB	AX,AX
  6457                              <1> 	; 05/12/2021
  6458 00002B30 29C0                <1> 	sub	eax, eax
  6459                              <1> 	; 27/12/2014 
  6460                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6461                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6462                              <1> 	;mov	di, bx			; HDPT offset
  6463 00002B32 89DF                <1> 	mov	edi, ebx
  6464                              <1> G5:
  6465 00002B34 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6466                              <1> 	;POP	ES
  6467 00002B35 1F                  <1> 	POP	DS
  6468                              <1> 	;RETf	2
  6469 00002B36 CA0400              <1> 	retf	4
  6470                              <1> G4:
  6471 00002B39 C605[CF700000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6472                              <1> 	; 05/12/2021
  6473 00002B40 29C0                <1> 	sub	eax, eax
  6474 00002B42 B407                <1> 	MOV	AH,INIT_FAIL
  6475                              <1> 	;SUB	AL,AL
  6476                              <1> 	;SUB	DX,DX
  6477 00002B44 29D2                <1> 	sub	edx, edx
  6478                              <1> 	;SUB	CX,CX
  6479 00002B46 29C9                <1> 	sub	ecx, ecx
  6480 00002B48 F9                  <1> 	STC				; SET ERROR FLAG
  6481 00002B49 EBE9                <1> 	JMP	short G5
  6482                              <1> 
  6483                              <1> ;----------------------------------------
  6484                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6485                              <1> ;----------------------------------------
  6486                              <1> 	; 03/01/2015
  6487                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6488                              <1> 	; logical sector per logical track
  6489                              <1> 	; and logical heads - 1 would be set but
  6490                              <1> 	; it is seen as it will be good
  6491                              <1> 	; if physical parameters will be set here
  6492                              <1> 	; because, number of heads <= 16.
  6493                              <1> 	; (logical heads usually more than 16)
  6494                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6495                              <1> 	;	== INT 13h physical parameters
  6496                              <1> 
  6497                              <1> ;INIT_DRV:
  6498                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6499                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6500                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6501                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6502                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6503                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6504                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6505                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6506                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6507                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6508                              <1> ;	SUB	AX,AX
  6509                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6510                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6511                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6512                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6513                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6514                              <1> ;	CALL	CHECK_STATUS
  6515                              <1> ;INIT_EXIT:
  6516                              <1> ;	RETn
  6517                              <1> 
  6518                              <1> ; 04/01/2015
  6519                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6520                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6521                              <1> INIT_DRV:
  6522                              <1> 	;xor	ah,ah
  6523 00002B4B 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6524 00002B4D B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6525 00002B4F 3825[E4700000]      <1>         cmp     [LBAMode], ah   ; 0
  6526 00002B55 7702                <1> 	ja	short idrv0
  6527 00002B57 B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6528                              <1> idrv0:
  6529                              <1> 	; DL = drive number (0 based)
  6530 00002B59 E8BB030000          <1> 	call	GET_VEC
  6531                              <1> 	;push	bx
  6532 00002B5E 53                  <1> 	push	ebx ; 21/02/2015
  6533                              <1> 	;add	bx,ax
  6534 00002B5F 01C3                <1> 	add	ebx,eax
  6535                              <1> 	;; 05/01/2015
  6536 00002B61 8A25[286B0000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6537                              <1> 	;;and 	ah,1 
  6538 00002B67 C0E404              <1> 	shl	ah,4
  6539 00002B6A 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6540                              <1> 	;mov	al,[es:bx]
  6541 00002B6D 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6542 00002B6F FEC8                <1> 	dec	al	 ; last head number 
  6543                              <1> 	;and	al,0Fh
  6544 00002B71 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6545                              <1> 	;
  6546 00002B73 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6547 00002B77 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6548                              <1> 	;pop	bx
  6549 00002B7A 5B                  <1> 	pop	ebx
  6550 00002B7B 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6551 00002B7D B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6552 00002B7F 803D[E4700000]00    <1> 	cmp	byte [LBAMode],0
  6553 00002B86 7702                <1> 	ja	short idrv1
  6554 00002B88 B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6555                              <1> idrv1:
  6556                              <1> 	;xor	ah,ah
  6557                              <1> 	;add	bx,ax
  6558 00002B8A 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6559                              <1> 	;mov	al,[es:bx]
  6560                              <1> 			; sector number
  6561 00002B8C 8A03                <1> 	mov	al,[ebx]
  6562 00002B8E 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6563 00002B91 28C0                <1> 	sub	al,al
  6564 00002B93 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6565 00002B96 E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6566 00002B9B 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6567 00002B9D E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6568 00002BA2 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6569 00002BA4 E8C3020000          <1> 	call	CHECK_STATUS
  6570                              <1> INIT_EXIT:
  6571 00002BA9 C3                  <1> 	RETn
  6572                              <1> 
  6573                              <1> ;----------------------------------------
  6574                              <1> ;	READ LONG	     (AH = 0AH) :
  6575                              <1> ;----------------------------------------
  6576                              <1> 
  6577                              <1> RD_LONG:
  6578                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6579 00002BAA C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6580 00002BAE E9E0000000          <1>         JMP     COMMANDI
  6581                              <1> 
  6582                              <1> ;----------------------------------------
  6583                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6584                              <1> ;----------------------------------------
  6585                              <1> 
  6586                              <1> WR_LONG:
  6587                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6588 00002BB3 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6589 00002BB7 E92C010000          <1>         JMP     COMMANDO
  6590                              <1> 
  6591                              <1> ;----------------------------------------
  6592                              <1> ;	SEEK		     (AH = 0CH) :
  6593                              <1> ;----------------------------------------
  6594                              <1> 
  6595                              <1> DISK_SEEK:
  6596 00002BBC C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6597 00002BC0 E89A010000          <1> 	CALL	COMMAND
  6598 00002BC5 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6599 00002BC7 E80C020000          <1> 	CALL	_WAIT
  6600 00002BCC 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6601 00002BCE E899020000          <1> 	CALL	CHECK_STATUS
  6602 00002BD3 803D[CF700000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6603 00002BDA 7507                <1> 	JNE	short DS_EXIT
  6604 00002BDC C605[CF700000]00    <1>         MOV     byte [DISK_STATUS1],0
  6605                              <1> DS_EXIT:
  6606 00002BE3 C3                  <1> 	RETn
  6607                              <1> 
  6608                              <1> ;----------------------------------------
  6609                              <1> ;	TEST DISK READY      (AH = 10H) :
  6610                              <1> ;----------------------------------------
  6611                              <1> 
  6612                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6613 00002BE4 E82B020000          <1> 	CALL	NOT_BUSY
  6614 00002BE9 751C                <1> 	JNZ	short TR_EX
  6615 00002BEB 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6616 00002BEE 668B15[246B0000]    <1> 	MOV	DX,[HF_PORT]
  6617 00002BF5 80C206              <1> 	add	dl,6
  6618 00002BF8 EE                  <1> 	OUT	DX,AL
  6619 00002BF9 E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6620 00002BFE 7507                <1> 	JNZ	short TR_EX
  6621 00002C00 C605[CF700000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6622                              <1> TR_EX:	
  6623 00002C07 C3                  <1> 	RETn
  6624                              <1> 
  6625                              <1> ;----------------------------------------
  6626                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6627                              <1> ;----------------------------------------
  6628                              <1> 
  6629                              <1> HDISK_RECAL:
  6630 00002C08 C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6631 00002C0C E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6632 00002C11 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6633 00002C13 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6634 00002C18 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6635 00002C1A E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6636 00002C1F 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6637                              <1> RECAL_X:
  6638 00002C21 E846020000          <1> 	CALL	CHECK_STATUS
  6639 00002C26 803D[CF700000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6640 00002C2D 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6641 00002C2F C605[CF700000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6642                              <1> RECAL_EXIT:
  6643 00002C36 803D[CF700000]00    <1>         CMP     byte [DISK_STATUS1],0
  6644 00002C3D C3                  <1> 	RETn
  6645                              <1> 
  6646                              <1> ;----------------------------------------
  6647                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6648                              <1> ;----------------------------------------
  6649                              <1> 
  6650                              <1> CTLR_DIAGNOSTIC:
  6651 00002C3E FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6652 00002C3F E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6653                              <1> 	;AND	AL,0BFH
  6654 00002C41 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6655                              <1> 	;JMP	$+2
  6656                              <1> 	IODELAY
  2077 00002C43 EB00                <2>  jmp short $+2
  2078 00002C45 EB00                <2>  jmp short $+2
  6657 00002C47 E6A1                <1> 	OUT	INTB01,AL
  6658                              <1> 	IODELAY
  2077 00002C49 EB00                <2>  jmp short $+2
  2078 00002C4B EB00                <2>  jmp short $+2
  6659 00002C4D E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6660 00002C4F 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6661                              <1> 	;JMP	$+2
  6662                              <1> 	IODELAY
  2077 00002C51 EB00                <2>  jmp short $+2
  2078 00002C53 EB00                <2>  jmp short $+2
  6663 00002C55 E621                <1> 	OUT	INTA01,AL
  6664 00002C57 FB                  <1> 	STI
  6665 00002C58 E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6666 00002C5D 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6667                              <1> 	;MOV	DX, HF_PORT+7
  6668 00002C5F 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6669 00002C66 80C207              <1> 	add	dl, 7
  6670 00002C69 B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6671 00002C6B EE                  <1> 	OUT	DX,AL
  6672 00002C6C E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6673 00002C71 B480                <1> 	MOV	AH,TIME_OUT
  6674 00002C73 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6675                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6676 00002C75 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6677 00002C7C FEC2                <1> 	inc	dl
  6678 00002C7E EC                  <1> 	IN	AL,DX
  6679 00002C7F A2[C6700000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6680 00002C84 B400                <1> 	MOV	AH,0
  6681 00002C86 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6682 00002C88 7402                <1> 	JE	SHORT CD_EXIT
  6683 00002C8A B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6684                              <1> CD_EXIT:
  6685 00002C8C 8825[CF700000]      <1> 	MOV	[DISK_STATUS1],AH
  6686 00002C92 C3                  <1> 	RETn
  6687                              <1> 
  6688                              <1> ;----------------------------------------
  6689                              <1> ; COMMANDI				:
  6690                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6691                              <1> ;	NSECTOR RETURNS ZERO		:
  6692                              <1> ;----------------------------------------
  6693                              <1> COMMANDI:
  6694 00002C93 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6695 00002C98 724D                <1> 	JC	short CMD_ABORT
  6696                              <1> 	;MOV	DI,BX
  6697 00002C9A 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6698 00002C9C E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6699 00002CA1 7544                <1> 	JNZ	short CMD_ABORT
  6700                              <1> CMD_I1:
  6701 00002CA3 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6702 00002CA8 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6703                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6704 00002CAA B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6705                              <1> 	;MOV	DX,HF_PORT
  6706 00002CAF 668B15[246B0000]    <1> 	mov	dx,[HF_PORT]
  6707 00002CB6 FA                  <1> 	CLI
  6708 00002CB7 FC                  <1> 	CLD
  6709 00002CB8 F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6710 00002CBB FB                  <1> 	STI
  6711 00002CBC F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6712 00002CC0 7419                <1> 	JZ	CMD_I3
  6713 00002CC2 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6714 00002CC7 721E                <1> 	JC	short TM_OUT
  6715                              <1> 	;MOV	DX,HF_PORT
  6716 00002CC9 668B15[246B0000]    <1> 	mov	dx,[HF_PORT]
  6717                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6718 00002CD0 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6719 00002CD5 EC                  <1> CMD_I2: IN	AL,DX
  6720                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6721 00002CD6 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6722 00002CD8 47                  <1> 	INC	eDI
  6723 00002CD9 E2FA                <1> 	LOOP	CMD_I2
  6724 00002CDB E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6725 00002CE0 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6726 00002CE2 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6727 00002CE5 75BC                <1> 	JNZ	SHORT CMD_I1
  6728                              <1> CMD_ABORT:
  6729 00002CE7 C3                  <1> TM_OUT: RETn
  6730                              <1> 
  6731                              <1> ;----------------------------------------
  6732                              <1> ; COMMANDO				:
  6733                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6734                              <1> ;	NSECTOR RETURNS ZERO		:
  6735                              <1> ;----------------------------------------
  6736                              <1> COMMANDO:
  6737 00002CE8 E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6738 00002CED 72F8                <1> 	JC	short CMD_ABORT
  6739 00002CEF 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6740 00002CF1 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6741 00002CF6 75EF                <1> 	JNZ	short CMD_ABORT
  6742 00002CF8 E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6743 00002CFD 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6744                              <1> CMD_O1: ;PUSH	DS
  6745                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6746                              <1> 	;POP	DS
  6747                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6748                              <1> 	;MOV	DX,HF_PORT
  6749                              <1> 	; 01/02/2015
  6750 00002CFF 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6751                              <1> 	;push	es
  6752                              <1> 	;pop	ds
  6753                              <1> 	;mov	cx, 256
  6754 00002D06 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6755 00002D0B FA                  <1> 	CLI
  6756 00002D0C FC                  <1> 	CLD
  6757 00002D0D F3666F              <1> 	REP	OUTSW
  6758 00002D10 FB                  <1> 	STI
  6759                              <1> 	;POP	DS			; RESTORE DS
  6760 00002D11 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6761 00002D15 7419                <1> 	JZ	short CMD_O3
  6762 00002D17 E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6763 00002D1C 72C9                <1> 	JC	short TM_OUT
  6764                              <1> 	;MOV	DX,HF_PORT
  6765 00002D1E 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6766                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6767 00002D25 B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6768                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6769 00002D2A 8A06                <1> 	mov	al, [esi]
  6770 00002D2C EE                  <1> 	OUT	DX,AL
  6771 00002D2D 46                  <1> 	INC	eSI
  6772 00002D2E E2FA                <1> 	LOOP	CMD_O2
  6773                              <1> CMD_O3:
  6774 00002D30 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6775 00002D35 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6776 00002D37 E830010000          <1> 	CALL	CHECK_STATUS
  6777 00002D3C 75A9                <1> 	JNZ	short CMD_ABORT
  6778 00002D3E F605[C5700000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6779 00002D45 75B8                <1> 	JNZ	SHORT CMD_O1
  6780                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6781 00002D47 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6782                              <1> 	;add	dl, 2
  6783 00002D4E FEC2                <1> 	inc	dl
  6784 00002D50 FEC2                <1> 	inc	dl
  6785 00002D52 EC                  <1> 	IN	AL,DX			;
  6786 00002D53 A8FF                <1> 	TEST	AL,0FFH 		;
  6787 00002D55 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6788 00002D57 C605[CF700000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6789                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6790                              <1> CMD_O4:
  6791 00002D5E C3                  <1> 	RETn
  6792                              <1> 
  6793                              <1> ;--------------------------------------------------------
  6794                              <1> ; COMMAND						:
  6795                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6796                              <1> ; OUTPUT						:
  6797                              <1> ;	BL = STATUS					:
  6798                              <1> ;	BH = ERROR REGISTER				:
  6799                              <1> ;--------------------------------------------------------
  6800                              <1> 
  6801                              <1> COMMAND:
  6802 00002D5F 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6803                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6804                              <1> COMMAND1:
  6805                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6806 00002D60 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6807                              <1> 	;;POP	CX
  6808 00002D65 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6809 00002D67 803D[CF700000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6810                              <1> 	;JZ	short CMD_TIMEOUT
  6811                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6812                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6813 00002D6E 7507                <1> 	jne	short COMMAND4
  6814                              <1> CMD_TIMEOUT:
  6815 00002D70 C605[CF700000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6816                              <1> COMMAND4:
  6817 00002D77 5B                  <1> 	POP	eBX
  6818 00002D78 803D[CF700000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6819 00002D7F C3                  <1> 	RETn
  6820                              <1> COMMAND2:
  6821 00002D80 5B                  <1> 	POP	eBX
  6822 00002D81 57                  <1> 	PUSH	eDI
  6823 00002D82 C605[C7700000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6824 00002D89 FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6825 00002D8A E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6826                              <1> 	;AND	AL,0BFH
  6827 00002D8C 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6828                              <1> 	;JMP	$+2
  6829                              <1> 	IODELAY
  2077 00002D8E EB00                <2>  jmp short $+2
  2078 00002D90 EB00                <2>  jmp short $+2
  6830 00002D92 E6A1                <1> 	OUT	INTB01,AL
  6831 00002D94 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6832 00002D96 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6833                              <1> 	;JMP	$+2
  6834                              <1> 	IODELAY
  2077 00002D98 EB00                <2>  jmp short $+2
  2078 00002D9A EB00                <2>  jmp short $+2
  6835 00002D9C E621                <1> 	OUT	INTA01,AL
  6836 00002D9E FB                  <1> 	STI
  6837 00002D9F 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6838                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6839 00002DA1 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6840 00002DA8 FEC2                <1> 	inc	dl
  6841 00002DAA F605[D1700000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6842 00002DB1 7411                <1> 	JZ	short COMMAND3
  6843 00002DB3 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6844 00002DB6 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6845 00002DB8 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6846 00002DBA 7208                <1> 	JB	short COMMAND3
  6847 00002DBC 3C40                <1> 	CMP	AL,40H
  6848 00002DBE 7704                <1> 	JA	short COMMAND3
  6849 00002DC0 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6850                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6851                              <1> COMMAND3:
  6852 00002DC4 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6853 00002DC8 EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6854                              <1> 	IODELAY
  2077 00002DC9 EB00                <2>  jmp short $+2
  2078 00002DCB EB00                <2>  jmp short $+2
  6855 00002DCD 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6856 00002DCE 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6857 00002DD0 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6858 00002DD4 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6859 00002DD6 5F                  <1> 	POP	eDI
  6860 00002DD7 C3                  <1> 	RETn				; ZERO FLAG IS SET
  6861                              <1> 
  6862                              <1> ;CMD_TIMEOUT:
  6863                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6864                              <1> ;COMMAND4:
  6865                              <1> ;	POP	BX
  6866                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6867                              <1> ;	RETn
  6868                              <1> 
  6869                              <1> ;----------------------------------------
  6870                              <1> ;	WAIT FOR INTERRUPT		:
  6871                              <1> ;----------------------------------------
  6872                              <1> ;WAIT:
  6873                              <1> _WAIT:
  6874 00002DD8 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6875                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6876                              <1> 	;CLC
  6877                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6878                              <1> 	;INT	15H
  6879                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6880                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6881                              <1> 
  6882                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6883                              <1> 	;; 21/02/2015
  6884                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6885                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6886 00002DD9 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6887                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6888                              <1> ;-----	WAIT LOOP
  6889                              <1> 
  6890                              <1> WT1:	
  6891                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6892 00002DDE F605[C7700000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6893                              <1> 	;LOOPZ	WT1
  6894 00002DE5 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6895                              <1> 	;DEC	BL
  6896                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6897                              <1> 
  6898                              <1> WT1_hi:
  6899 00002DE7 E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6900 00002DE9 A810                <1> 	test	al, 10h			; transition on memory
  6901 00002DEB 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6902                              <1> WT1_lo:
  6903 00002DED E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6904 00002DEF A810                <1> 	test	al, 10h			
  6905 00002DF1 74FA                <1> 	jz	short WT1_lo
  6906 00002DF3 E2E9                <1> 	loop	WT1
  6907                              <1> 	;;or	bl, bl
  6908                              <1> 	;;jz	short WT2	
  6909                              <1> 	;;dec	bl
  6910                              <1> 	;;jmp	short WT1
  6911                              <1> 	;dec	bl
  6912                              <1> 	;jnz	short WT1	
  6913                              <1> 
  6914 00002DF5 C605[CF700000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6915 00002DFC EB0E                <1> 	JMP	SHORT WT4
  6916 00002DFE C605[CF700000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6917 00002E05 C605[C7700000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6918 00002E0C 803D[CF700000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6919 00002E13 C3                  <1> 	RETn
  6920                              <1> 
  6921                              <1> ;----------------------------------------
  6922                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6923                              <1> ;----------------------------------------
  6924                              <1> NOT_BUSY:
  6925 00002E14 FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6926                              <1> 	;PUSH	eBX
  6927                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6928 00002E15 668B15[246B0000]    <1> 	mov	DX, [HF_PORT]
  6929 00002E1C 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  6930                              <1> 	;MOV	BL,DELAY_1
  6931                              <1> 					; wait for 10 seconds
  6932                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  6933                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  6934                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  6935 00002E1F B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  6936                              <1> 	;
  6937                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  6938                              <1> NB1:	
  6939 00002E24 EC                  <1> 	IN	AL,DX			; CHECK STATUS
  6940                              <1> 	;TEST	AL,ST_BUSY
  6941 00002E25 2480                <1> 	and	al, ST_BUSY
  6942                              <1> 	;LOOPNZ	NB1
  6943 00002E27 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  6944                              <1> 	;DEC	BL			
  6945                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  6946                              <1> 
  6947 00002E29 E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  6948 00002E2B A810                <1> 	TEST	AL,010H			; transition on memory
  6949 00002E2D 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  6950 00002E2F E461                <1> NB1_lo: IN	AL,SYS1
  6951 00002E31 A810                <1> 	TEST	AL,010H
  6952 00002E33 74FA                <1> 	JZ	short NB1_lo
  6953 00002E35 E2ED                <1> 	LOOP	NB1
  6954                              <1> 	;dec	bl
  6955                              <1> 	;jnz	short NB1
  6956                              <1> 	;
  6957                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  6958                              <1> ;;	jb	short NB1
  6959                              <1> 	;
  6960                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  6961                              <1> 	;JMP	SHORT NB3
  6962 00002E37 B080                <1> 	mov	al, TIME_OUT
  6963                              <1> NB2:	
  6964                              <1> 	;MOV	byte [DISK_STATUS1],0
  6965                              <1> ;NB3:	
  6966                              <1> 	;POP	eBX
  6967 00002E39 A2[CF700000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  6968                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6969 00002E3E 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  6970 00002E40 C3                  <1> 	RETn
  6971                              <1> 
  6972                              <1> ;----------------------------------------
  6973                              <1> ;	WAIT FOR DATA REQUEST		:
  6974                              <1> ;----------------------------------------
  6975                              <1> WAIT_DRQ:
  6976                              <1> 	;MOV	CX,DELAY_3
  6977                              <1> 	;MOV	DX,HF_PORT+7
  6978 00002E41 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  6979 00002E48 80C207              <1> 	add	dl, 7
  6980                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  6981                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  6982                              <1> 					; (but it is written as 2000
  6983                              <1> 					; micro seconds in ATORGS.ASM file
  6984                              <1> 					; of Award Bios - 1999, D1A0622)
  6985 00002E4B B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  6986 00002E50 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  6987 00002E51 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  6988 00002E53 7516                <1> 	JNZ	short WQ_OK
  6989                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  6990                              <1> WQ_hi:	
  6991 00002E55 E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  6992 00002E57 A810                <1> 	TEST	AL,010H			; transition on memory
  6993 00002E59 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  6994 00002E5B E461                <1> WQ_lo:  IN      AL,SYS1
  6995 00002E5D A810                <1> 	TEST	AL,010H
  6996 00002E5F 74FA                <1> 	JZ	SHORT WQ_lo
  6997 00002E61 E2ED                <1> 	LOOP	WQ_1
  6998                              <1> 
  6999 00002E63 C605[CF700000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7000 00002E6A F9                  <1> 	STC
  7001                              <1> WQ_OK:
  7002 00002E6B C3                  <1> 	RETn
  7003                              <1> ;WQ_OK:	;CLC
  7004                              <1> ;	RETn
  7005                              <1> 
  7006                              <1> ;----------------------------------------
  7007                              <1> ;	CHECK FIXED DISK STATUS 	:
  7008                              <1> ;----------------------------------------
  7009                              <1> CHECK_STATUS:
  7010 00002E6C E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7011 00002E71 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7012 00002E73 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7013 00002E75 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7014 00002E77 E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7015                              <1> CHECK_S1:
  7016 00002E7C 803D[CF700000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7017 00002E83 C3                  <1> 	RETn
  7018                              <1> 
  7019                              <1> ;----------------------------------------
  7020                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7021                              <1> ;----------------------------------------
  7022                              <1> CHECK_ST:
  7023                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7024 00002E84 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]
  7025 00002E8B 80C207              <1> 	add	dl, 7
  7026 00002E8E EC                  <1> 	IN	AL,DX
  7027 00002E8F A2[C5700000]        <1> 	MOV	[HF_STATUS],AL
  7028 00002E94 B400                <1> 	MOV	AH,0
  7029 00002E96 A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7030 00002E98 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7031 00002E9A B4CC                <1> 	MOV	AH,WRITE_FAULT
  7032 00002E9C A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7033 00002E9E 7514                <1> 	JNZ	short CKST_EXIT
  7034 00002EA0 B4AA                <1> 	MOV	AH,NOT_RDY
  7035 00002EA2 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7036 00002EA4 740E                <1> 	JZ	short CKST_EXIT
  7037 00002EA6 B440                <1> 	MOV	AH,BAD_SEEK
  7038 00002EA8 A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7039 00002EAA 7408                <1> 	JZ	short CKST_EXIT
  7040 00002EAC B411                <1> 	MOV	AH,DATA_CORRECTED
  7041 00002EAE A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7042 00002EB0 7502                <1> 	JNZ	short CKST_EXIT
  7043 00002EB2 B400                <1> 	MOV	AH,0
  7044                              <1> CKST_EXIT:
  7045 00002EB4 8825[CF700000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7046 00002EBA 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7047 00002EBD 7403                <1> 	JZ	short CKST_EX1
  7048 00002EBF 80FC00              <1> 	CMP	AH,0
  7049                              <1> CKST_EX1:
  7050 00002EC2 C3                  <1> 	RETn
  7051                              <1> 
  7052                              <1> ;----------------------------------------
  7053                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7054                              <1> ;----------------------------------------
  7055                              <1> CHECK_ER:
  7056                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7057 00002EC3 668B15[246B0000]    <1> 	mov	dx, [HF_PORT]		;
  7058 00002ECA FEC2                <1> 	inc	dl
  7059 00002ECC EC                  <1> 	IN	AL,DX
  7060 00002ECD A2[C6700000]        <1> 	MOV	[HF_ERROR],AL
  7061 00002ED2 53                  <1> 	PUSH	eBX ; 21/02/2015
  7062 00002ED3 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7063 00002ED8 D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7064 00002EDA 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7065 00002EDC E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7066 00002EDE BB[186B0000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7067 00002EE3 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7068                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7069                              <1> 	;mov	ah, [bx]
  7070 00002EE5 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7071 00002EE7 8825[CF700000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7072 00002EED 5B                  <1> 	POP	eBX
  7073 00002EEE 80FC00              <1> 	CMP	AH,0
  7074 00002EF1 C3                  <1> 	RETn
  7075                              <1> 
  7076                              <1> ;--------------------------------------------------------
  7077                              <1> ; CHECK_DMA						:
  7078                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7079                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7080                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7081                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7082                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7083                              <1> ;  -ERROR OTHERWISE					:
  7084                              <1> ;--------------------------------------------------------
  7085                              <1> CHECK_DMA:
  7086                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7087                              <1> 	; 05/12/2021
  7088 00002EF2 50                  <1> 	push	eax
  7089 00002EF3 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7090 00002EF7 F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7091 00002EFB 7404                <1> 	JZ	short CKD1
  7092 00002EFD 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7093 00002F01 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7094 00002F04 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7095 00002F06 7207                <1> 	JB	short CKDERR		; TOO MANY
  7096 00002F08 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7097 00002F0A 7203                <1> 	JB	short CKDERR		; ERROR
  7098 00002F0C F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7099                              <1> 	;POP	AX
  7100                              <1> 	; 05/12/2021
  7101 00002F0D 58                  <1> 	pop	eax
  7102 00002F0E C3                  <1> 	RETn				; NORMAL RETURN
  7103 00002F0F F9                  <1> CKDERR: STC				; INDICATE ERROR
  7104 00002F10 C605[CF700000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7105                              <1> 	;POP	AX
  7106                              <1> 	; 05/12/2021
  7107 00002F17 58                  <1> 	pop	eax	
  7108 00002F18 C3                  <1> 	RETn
  7109                              <1> 
  7110                              <1> ;----------------------------------------
  7111                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7112                              <1> ;----------------------------------------
  7113                              <1> 					
  7114                              <1> ; INPUT -> DL = 0 based drive number
  7115                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7116                              <1> 
  7117                              <1> GET_VEC:
  7118                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7119                              <1> 	;MOV	ES,AX
  7120                              <1> 	;TEST	DL,1
  7121                              <1> 	;JZ	short GV_0
  7122                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7123                              <1> ;	JMP	SHORT GV_EXIT
  7124                              <1> ;GV_0:
  7125                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7126                              <1> ;
  7127                              <1> 	;xor	bh, bh
  7128 00002F19 31DB                <1> 	xor	ebx, ebx
  7129 00002F1B 88D3                <1> 	mov	bl, dl
  7130                              <1> 	;;02/01/2015
  7131                              <1> 	;;shl	bl, 1			; port address offset
  7132                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7133                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7134 00002F1D C0E302              <1> 	shl	bl, 2	;;
  7135                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7136 00002F20 81C3[D4700000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7137                              <1> 	;push	word [bx+2]		; dpt segment
  7138                              <1> 	;pop	es
  7139                              <1> 	;mov	bx, [bx]		; dpt offset
  7140 00002F26 8B1B                <1> 	mov	ebx, [ebx]		
  7141                              <1> ;GV_EXIT:
  7142 00002F28 C3                  <1> 	RETn
  7143                              <1> 
  7144                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7145                              <1> hdc1_int: ; 21/02/2015
  7146                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7147                              <1> ;								:
  7148                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7149                              <1> ;								:
  7150                              <1> ;----------------------------------------------------------------
  7151                              <1> 
  7152                              <1> ; 22/12/2014
  7153                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7154                              <1> ;	 '11/15/85'
  7155                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7156                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7157                              <1> 
  7158                              <1> ;int_76h:
  7159                              <1> HD_INT:
  7160                              <1> 	;push	ax
  7161                              <1> 	; 05/12/2021
  7162 00002F29 50                  <1> 	push	eax
  7163 00002F2A 1E                  <1> 	push	ds
  7164                              <1> 	;CALL	DDS
  7165                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7166 00002F2B 66B81000            <1> 	mov	ax, KDATA
  7167 00002F2F 8ED8                <1> 	mov 	ds, ax
  7168                              <1> 	;
  7169                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7170                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7171 00002F31 C605[C7700000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7172                              <1> 	;
  7173                              <1> 	;push	dx
  7174                              <1> 	; 05/12/2021
  7175 00002F38 52                  <1> 	push	edx
  7176 00002F39 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7177                              <1> 					; Clear Controller
  7178                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7179 00002F3D EC                  <1> 	in	al, dx			;
  7180                              <1> 	;pop	dx
  7181                              <1> 	; 05/12/2021
  7182 00002F3E 5A                  <1> 	pop	edx
  7183                              <1> 	NEWIODELAY
  2082 00002F3F E6EB                <2>  out 0EBh,al
  7184                              <1> 	;
  7185 00002F41 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7186 00002F43 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7187                              <1> 	;JMP	$+2			; WAIT
  7188                              <1> 	NEWIODELAY
  2082 00002F45 E6EB                <2>  out 0EBh,al
  7189 00002F47 E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7190 00002F49 1F                  <1> 	pop	ds
  7191                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7192                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7193                              <1> 	;INT	15H			;  INTERRUPT
  7194                              <1> irq15_iret: ; 25/02/2015
  7195                              <1> 	;pop	ax
  7196                              <1> 	; 05/12/2021
  7197 00002F4A 58                  <1> 	pop	eax
  7198 00002F4B CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7199                              <1> 
  7200                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  7201                              <1> hdc2_int: ; 21/02/2015
  7202                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7203                              <1> ;								:
  7204                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7205                              <1> ;								:
  7206                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7207                              <1> 
  7208                              <1> ;int_77h:
  7209                              <1> HD1_INT:
  7210                              <1> 	;push	ax
  7211                              <1> 	; 05/12/2021
  7212 00002F4C 50                  <1> 	push	eax
  7213                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7214                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7215 00002F4D B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7216 00002F4F E6A0                <1> 	out	0A0h, al
  7217 00002F51 EB00                <1>         jmp short $+2
  7218 00002F53 EB00                <1> 	jmp short $+2
  7219 00002F55 E4A0                <1> 	in	al, 0A0h
  7220 00002F57 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7221 00002F59 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7222                              <1> 	;
  7223 00002F5B 1E                  <1> 	push	ds
  7224                              <1> 	;CALL	DDS
  7225                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7226 00002F5C 66B81000            <1> 	mov	ax, KDATA
  7227 00002F60 8ED8                <1> 	mov 	ds, ax
  7228                              <1> 	;
  7229                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7230                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7231 00002F62 800D[C7700000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7232                              <1> 	;
  7233                              <1> 	;push	dx
  7234                              <1> 	; 05/12/2021
  7235 00002F69 52                  <1> 	push	edx
  7236 00002F6A 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7237                              <1> 					; Clear Controller (Award BIOS 1999)
  7238 00002F6E EBCD                <1> 	jmp	short Clear_IRQ1415
  7239                              <1> 
  7240                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7241                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7242                              <1> 
  7243                              <1> ;////////////////////////////////////////////////////////////////////
  7244                              <1> ;; END OF DISK I/O SYTEM ///
  2017                                  %include 'memory.s'  ; 09/03/2015
  2018                              <1> ; Retro UNIX 386 v2 - memory.s - 26/01/2020
  2019                              <1> ; Last Modification: 31/12/2021 (Retro UNIX 386 v1.2)
  2020                              <1> ; ----------------------------------------------------------------------------
  2021                              <1> ;
  2022                              <1> ; MEMORY.ASM - Retro UNIX 386 v1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2023                              <1> ; Retro UNIX 386 v1 Kernel (unix386.s, v0.2.0.14) - MEMORY.INC
  2024                              <1> ; 18/10/2015 (!not completed!)
  2025                              <1> ;
  2026                              <1> ; Source code for NASM - Netwide Assembler (2.11)
  2027                              <1> 
  2028                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2029                              <1> 
  2030                              <1> ;;04/11/2014 (unix386.s)	
  2031                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2032                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2033                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2034                              <1> ;;
  2035                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2036                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2037                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2038                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2039                              <1> 
  2040                              <1> ; 27/04/2015
  2041                              <1> ; 09/03/2015
  2042                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2043                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2044                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2045                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2046                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2047                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2048                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2049                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2050                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2051                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2052                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2053                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2054                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2055                              <1> SWP_DISK_READ_ERR 	   equ 40
  2056                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2057                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2058                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2059                              <1> SWP_DISK_WRITE_ERR         equ 44
  2060                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2061                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2062                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2063                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2064                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2065                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2066                              <1> 					; (Indicates that the page is not allocated
  2067                              <1> 					; for the process, it is a shared or system
  2068                              <1>                                         ; page, it must not be deallocated!)
  2069                              <1> ; 14/12/2020
  2070                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2071                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2072                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2073                              <1> 				; (Out of memory allocation table)	
  2074                              <1> ;
  2075                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2076                              <1> ;;
  2077                              <1> ;; 10/10/2014
  2078                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2079                              <1> ;;
  2080                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2081                              <1> ;;	(virtual address = physical address)
  2082                              <1> ;; KERNEL PAGE TABLES:
  2083                              <1> ;;	Kernel page directory and all page tables are
  2084                              <1> ;;	on memory as initialized, as equal to physical memory
  2085                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2086                              <1> ;;
  2087                              <1> ;;	what for: User pages may be swapped out, when accessing
  2088                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2089                              <1> ;;	kernel would have to swap it in! But it is also may be
  2090                              <1> ;;	in use by a user process. (In system/kernel mode
  2091                              <1> ;;	kernel can access all memory pages even if they are
  2092                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2093                              <1> ;;	cause conflicts.) 
  2094                              <1> ;;	
  2095                              <1> ;;	As result of these conditions,
  2096                              <1> ;;	all kernel pages must be initialized as equal to 
  2097                              <1> ;;	physical layout for preventing page faults. 
  2098                              <1> ;;	Also, calling "allocate page" procedure after
  2099                              <1> ;;	a page fault can cause another page fault (double fault)
  2100                              <1> ;;	if all kernel page tables would not be initialized.
  2101                              <1> ;;
  2102                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2103                              <1> ;;	memory allocation table. (double word aligned)
  2104                              <1> ;;
  2105                              <1> ;;	[next_page] = first/next free space to be searched
  2106                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2107                              <1> ;;
  2108                              <1> ;;	[last_page] = End of memory (users space), as offset
  2109                              <1> ;;	to memory allocation table. (double word aligned)
  2110                              <1> ;;
  2111                              <1> ;; USER PAGE TABLES:
  2112                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2113                              <1> ;;		'ready only' marked copies of the 
  2114                              <1> ;;		parent process's page table entries (for
  2115                              <1> ;;		same physical memory).
  2116                              <1> ;;		(A page will be copied to a new page after
  2117                              <1> ;;		 if it causes R/W page fault.)
  2118                              <1> ;;
  2119                              <1> ;;	Every user process has own (different)
  2120                              <1> ;;	page directory and page tables.	
  2121                              <1> ;;
  2122                              <1> ;;	Code starts at virtual address 0, always.
  2123                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2124                              <1> ;;	(Programs can be written/developed as simple
  2125                              <1> ;;	 flat memory programs.)
  2126                              <1> ;;
  2127                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2128                              <1> ;;	Memory page will be allocated by kernel only 
  2129                              <1> ;;		(in kernel/system mode only).
  2130                              <1> ;;	* After a
  2131                              <1> ;;	  - 'not present' page fault
  2132                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2133                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2134                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2135                              <1> ;;	  request by running process.
  2136                              <1> ;;	* While creating a process, allocating a new buffer,
  2137                              <1> ;;	  new page tables etc.
  2138                              <1> ;;
  2139                              <1> ;;	At first,
  2140                              <1> ;;	- 'allocate page' procedure will be called;
  2141                              <1> ;,	   if it will return with a valid (>0) physical address
  2142                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2143                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2144                              <1> ;;	- 'allocate page' will be called for allocating page
  2145                              <1> ;;	   directory, page table and running space (data/code).
  2146                              <1> ;;	- every successful 'allocate page' call will decrease
  2147                              <1> ;;	  'free_pages' count (pointer).
  2148                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2149                              <1> ;;	  if 'free_pages' points to a ZERO.
  2150                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2151                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2152                              <1> ;;	  error except errors caused by attribute conflicts.
  2153                              <1> ;;	 (swapper functions)	 
  2154                              <1> ;;					
  2155                              <1> ;;	At second,
  2156                              <1> ;;	- page directory entry will be updated then page table
  2157                              <1> ;;	  entry will be updated.		
  2158                              <1> ;;
  2159                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2160                              <1> ;;	- M.A.T. has a size according to available memory as
  2161                              <1> ;;	  follows:
  2162                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2163                              <1> ;;		  - a bit with value of 0 means allocated page
  2164                              <1> ;;		  - a bit with value of 1 means a free page
  2165                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2166                              <1> ;;	  depending on M.A.T.
  2167                              <1> ;;		(NOTE: Free page count will not be checked
  2168                              <1> ;;		again -on M.A.T.- after initialization. 
  2169                              <1> ;;		Kernel will trust on initial count.)
  2170                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2171                              <1> ;;	  and it will be increased by deallocation procedures.
  2172                              <1> ;;	
  2173                              <1> ;;	- Available memory will be calculated during
  2174                              <1> ;;	  the kernel's initialization stage (in real mode).
  2175                              <1> ;;	  Memory allocation table and kernel page tables 
  2176                              <1> ;;	  will be formatted/sized as result of available
  2177                              <1> ;;	  memory calculation before paging is enabled.
  2178                              <1> ;;
  2179                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2180                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2181                              <1> ;;	- Memory allocation for kernel page directory size 
  2182                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2183                              <1> ;;	  for page tables)
  2184                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2185                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2186                              <1> ;;	- User (available) space will be started 
  2187                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2188                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2189                              <1> ;;	  memory allocation table and kernel's page directory
  2190                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2191                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2192                              <1> ;; 	  for buffers.
  2193                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2194                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2195                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2196                              <1> ;;
  2197                              <1> ;; For 1GB Available Memory:
  2198                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2199                              <1> ;;	- Memory allocation for kernel page directory size 
  2200                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2201                              <1> ;;	  for page tables)
  2202                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2203                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2204                              <1> ;;	- User (available) space will be started 
  2205                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2206                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2207                              <1> ;;	  memory allocation table and kernel's page directory
  2208                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2209                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2210                              <1> ;; 	  for buffers.
  2211                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2212                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2213                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2214                              <1> ;;
  2215                              <1> ;;
  2216                              <1> 
  2217                              <1> ;;************************************************************************************
  2218                              <1> ;; 
  2219                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2220                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2221                              <1> 
  2222                              <1> ;; Main factor: "sys fork" system call 
  2223                              <1> ;;	
  2224                              <1> ;; 		FORK
  2225                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2226                              <1> ;;  writable pages ---->|
  2227                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2228                              <1> ;; 
  2229                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2230                              <1> ;; 
  2231                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2232                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2233                              <1> ;;       -while R/W bit is 0-. 
  2234                              <1> ;; 
  2235                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2236                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2237                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2238                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2239                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2240                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2241                              <1> ;; 
  2242                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2243                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2244                              <1> ;;   Parent's PTE attributes are not changed.
  2245                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2246                              <1> ;;    destroy/mix previous fork result).
  2247                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2248                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2249                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2250                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2251                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2252                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2253                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2254                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2255                              <1> ;; 
  2256                              <1> ;; !? WHAT FOR (duplication after duplication):
  2257                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2258                              <1> ;; program/executable code continues from specified location as child process, 
  2259                              <1> ;; returns back previous code location as parent process, every child after 
  2260                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2261                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2262                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2263                              <1> ;; was copied to child's process segment (all of code and data) according to
  2264                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2265                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2266                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2267                              <1> ;; (complete running image of parent process) to the child process; 
  2268                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2269                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2270                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2271                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2272                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2273                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2274                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2275                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2276                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2277                              <1> ;; for sharing same read only pages between parent and child processes.
  2278                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2279                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2280                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2281                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2282                              <1> ;; -deallocation problem-.
  2283                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2284                              <1> ;; 
  2285                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2286                              <1> ;; # Page fault handler will do those:
  2287                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2288                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2289                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2290                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2291                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2292                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2293                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2294                              <1> ;;     to child process.)	
  2295                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2296                              <1> ;; # Page fault handler will do those:
  2297                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2298                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2299                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2300                              <1> ;;     address or not. 
  2301                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2302                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2303                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2304                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2305                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2306                              <1> ;; 
  2307                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2308                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2309                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2310                              <1> ;;       duplication method details, it is not possible multiple child processes
  2311                              <1> ;;       were using same page with duplicated PTEs.
  2312                              <1> ;; 
  2313                              <1> ;;************************************************************************************   
  2314                              <1> 
  2315                              <1> ;; 08/10/2014
  2316                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2317                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2318                              <1> 
  2319                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2320                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2321                              <1> ;; (25/08/2014, Revision: 5057) file 
  2322                              <1> ;; by KolibriOS Team (2004-2012)
  2323                              <1> 
  2324                              <1> allocate_page:
  2325                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2326                              <1> 	;	 (temporary modifications)
  2327                              <1> 	; 01/07/2015
  2328                              <1> 	; 05/05/2015
  2329                              <1> 	; 30/04/2015
  2330                              <1> 	; 16/10/2014
  2331                              <1> 	; 08/10/2014
  2332                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2333                              <1> 	;
  2334                              <1> 	; INPUT -> none
  2335                              <1> 	;
  2336                              <1> 	; OUTPUT ->
  2337                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2338                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2339                              <1> 	;
  2340                              <1> 	;	CF = 1 and EAX = 0 
  2341                              <1> 	; 		   if there is not a free page to be allocated	
  2342                              <1> 	;
  2343                              <1> 	; Modified Registers -> none (except EAX)
  2344                              <1> 	;
  2345 00002F70 A1[40700000]        <1> 	mov	eax, [free_pages]
  2346 00002F75 21C0                <1> 	and	eax, eax
  2347 00002F77 7438                <1> 	jz	short out_of_memory
  2348                              <1> 	;
  2349 00002F79 53                  <1> 	push	ebx
  2350 00002F7A 51                  <1> 	push	ecx
  2351                              <1> 	;
  2352 00002F7B BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2353 00002F80 89D9                <1> 	mov	ecx, ebx
  2354                              <1>  				     ; NOTE: 32 (first_page) is initial
  2355                              <1> 				     ; value of [next_page].
  2356                              <1> 				     ; It points to the first available
  2357                              <1> 				     ; page block for users (ring 3) ...	
  2358                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2359                              <1> 				     ; (at the of the first 4 MB)		
  2360 00002F82 031D[44700000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2361                              <1> 				 ; next_free_page >> 5
  2362 00002F88 030D[48700000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2363                              <1> 				 ; (total_pages - 1) >> 5
  2364                              <1> al_p_scan:
  2365 00002F8E 39CB                <1> 	cmp	ebx, ecx
  2366 00002F90 770A                <1> 	ja	short al_p_notfound
  2367                              <1> 	;
  2368                              <1> 	; 01/07/2015
  2369                              <1> 	; AMD64 Architecture Programmers Manual
  2370                              <1> 	; Volume 3:
  2371                              <1> 	; General-Purpose and System Instructions
  2372                              <1> 	;
  2373                              <1> 	; BSF - Bit Scan Forward
  2374                              <1> 	;
  2375                              <1> 	;   Searches the value in a register or a memory location
  2376                              <1> 	;   (second operand) for the least-significant set bit. 
  2377                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2378                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2379                              <1> 	;   register (first operand). If the second operand contains 0, 
  2380                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2381                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2382                              <1> 	;   of the searched value
  2383                              <1> 	;
  2384 00002F92 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2385                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2386                              <1> 			   ; loads the destination with an index to
  2387                              <1> 			   ; first set bit. (0 -> 31) 
  2388                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2389 00002F95 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2390                              <1> 			 ;
  2391                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2392                              <1> 			 ;	  with value of 1 means 
  2393                              <1> 			 ;	  the corresponding page is free 
  2394                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2395 00002F97 83C304              <1> 	add	ebx, 4
  2396                              <1> 			 ; We return back for searching next page block
  2397                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2398                              <1> 			 ;	 we always will find at least 1 free page here.
  2399 00002F9A EBF2                <1>         jmp     short al_p_scan
  2400                              <1> 	;
  2401                              <1> al_p_notfound:
  2402 00002F9C 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2403 00002FA2 890D[44700000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2404                              <1> 				 ; (deallocate_page procedure will change it)
  2405 00002FA8 31C0                <1> 	xor	eax, eax
  2406 00002FAA A3[40700000]        <1> 	mov	[free_pages], eax ; 0
  2407 00002FAF 59                  <1> 	pop	ecx
  2408 00002FB0 5B                  <1> 	pop	ebx
  2409                              <1> 	;
  2410                              <1> ; 17/04/2021
  2411                              <1> ; ('swap_out' procedure call is disabled as temporary)
  2412                              <1> 
  2413                              <1> out_of_memory:
  2414                              <1> ;	call	swap_out
  2415                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2416                              <1> ;	;
  2417                              <1> ;	sub 	eax, eax ; 0
  2418 00002FB1 F9                  <1> 	stc
  2419 00002FB2 C3                  <1> 	retn
  2420                              <1> 
  2421                              <1> al_p_found:
  2422 00002FB3 89D9                <1> 	mov	ecx, ebx
  2423 00002FB5 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2424 00002FBB 890D[44700000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2425                              <1> 				 ; address/offset (to the next)
  2426 00002FC1 FF0D[40700000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2427                              <1> 	;
  2428 00002FC7 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2429                              <1> 				 ; is copied into the Carry Flag and then cleared
  2430                              <1> 				 ; in the destination.
  2431                              <1> 				 ;
  2432                              <1> 				 ; Reset the bit which is corresponding to the 
  2433                              <1> 				 ; (just) allocated page.
  2434                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2435 00002FCA C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2436 00002FCD 01C8                <1> 	add	eax, ecx	 ; = page number
  2437 00002FCF C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2438                              <1> 	; EAX = physical address of memory page
  2439                              <1> 	;
  2440                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2441                              <1> 	;       according to this EAX value...
  2442 00002FD2 59                  <1> 	pop	ecx
  2443 00002FD3 5B                  <1> 	pop	ebx
  2444                              <1> al_p_ok:
  2445 00002FD4 C3                  <1> 	retn
  2446                              <1> 
  2447                              <1> make_page_dir:
  2448                              <1> 	; 18/04/2015
  2449                              <1> 	; 12/04/2015
  2450                              <1> 	; 23/10/2014
  2451                              <1> 	; 16/10/2014
  2452                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2453                              <1> 	;
  2454                              <1> 	; INPUT ->
  2455                              <1> 	;	none
  2456                              <1> 	; OUTPUT ->
  2457                              <1> 	;	(EAX = 0)
  2458                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2459                              <1> 	;	cf = 0 ->
  2460                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2461                              <1> 	;		  process/user.
  2462                              <1> 	;
  2463                              <1> 	; Modified Registers -> EAX
  2464                              <1> 	;
  2465 00002FD5 E896FFFFFF          <1> 	call	allocate_page
  2466 00002FDA 7216                <1> 	jc	short mkpd_error
  2467                              <1> 	;
  2468 00002FDC A3[98710000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2469                              <1> 				  ; (Physical address)
  2470                              <1> clear_page:
  2471                              <1> 	; 18/04/2015
  2472                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2473                              <1> 	;
  2474                              <1> 	; INPUT ->
  2475                              <1> 	;	EAX = physical address of the page
  2476                              <1> 	; OUTPUT ->
  2477                              <1> 	;	all bytes of the page will be cleared
  2478                              <1> 	;
  2479                              <1> 	; Modified Registers -> none
  2480                              <1> 	;
  2481 00002FE1 57                  <1> 	push	edi
  2482 00002FE2 51                  <1> 	push	ecx
  2483 00002FE3 50                  <1> 	push	eax
  2484 00002FE4 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2485 00002FE9 89C7                <1> 	mov	edi, eax
  2486 00002FEB 31C0                <1> 	xor	eax, eax
  2487 00002FED F3AB                <1> 	rep	stosd
  2488 00002FEF 58                  <1> 	pop	eax
  2489 00002FF0 59                  <1> 	pop	ecx
  2490 00002FF1 5F                  <1> 	pop	edi
  2491                              <1> mkpd_error:
  2492                              <1> mkpt_error:
  2493 00002FF2 C3                  <1> 	retn
  2494                              <1> 
  2495                              <1> make_page_table:
  2496                              <1> 	; 23/06/2015
  2497                              <1> 	; 18/04/2015
  2498                              <1> 	; 12/04/2015
  2499                              <1> 	; 16/10/2014
  2500                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2501                              <1> 	;
  2502                              <1> 	; INPUT ->
  2503                              <1> 	;	EBX = virtual (linear) address
  2504                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2505                              <1> 	;	      (higher 20 bits must be ZERO)
  2506                              <1> 	;	      (bit 0 must be 1)	 
  2507                              <1> 	;	u.pgdir = page directory (physical) address
  2508                              <1> 	; OUTPUT ->
  2509                              <1> 	;	EDX = Page directory entry address
  2510                              <1> 	;	EAX = Page table address
  2511                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2512                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2513                              <1> 	;
  2514                              <1> 	; Modified Registers -> EAX, EDX
  2515                              <1> 	;
  2516 00002FF3 E878FFFFFF          <1> 	call	allocate_page
  2517 00002FF8 72F8                <1> 	jc	short mkpt_error
  2518 00002FFA E811000000          <1> 	call	set_pde	
  2519 00002FFF EBE0                <1> 	jmp	short clear_page
  2520                              <1> 
  2521                              <1> make_page:
  2522                              <1> 	; 24/07/2015
  2523                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2524                              <1> 	;
  2525                              <1> 	; INPUT ->
  2526                              <1> 	;	EBX = virtual (linear) address
  2527                              <1> 	;	ECX = page attributes (lower 12 bits)
  2528                              <1> 	;	      (higher 20 bits must be ZERO)
  2529                              <1> 	;	      (bit 0 must be 1)	 
  2530                              <1> 	;	u.pgdir = page directory (physical) address
  2531                              <1> 	; OUTPUT ->
  2532                              <1> 	;	EBX = Virtual address
  2533                              <1> 	;	(EDX = PTE value)
  2534                              <1> 	;	EAX = Physical address
  2535                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2536                              <1> 	;
  2537                              <1> 	; Modified Registers -> EAX, EDX
  2538                              <1> 	;
  2539 00003001 E86AFFFFFF          <1> 	call	allocate_page
  2540 00003006 7207                <1> 	jc	short mkp_err
  2541 00003008 E821000000          <1> 	call	set_pte	
  2542 0000300D 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2543                              <1> mkp_err:
  2544 0000300F C3                  <1> 	retn
  2545                              <1> 
  2546                              <1> set_pde:	; Set page directory entry (PDE)
  2547                              <1> 	; 20/07/2015
  2548                              <1> 	; 18/04/2015
  2549                              <1> 	; 12/04/2015
  2550                              <1> 	; 23/10/2014
  2551                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2552                              <1> 	;
  2553                              <1> 	; INPUT ->
  2554                              <1> 	;	EAX = physical address
  2555                              <1> 	;	      (use present value if EAX = 0)
  2556                              <1> 	;	EBX = virtual (linear) address
  2557                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2558                              <1> 	;	      (higher 20 bits must be ZERO)
  2559                              <1> 	;	      (bit 0 must be 1)	 
  2560                              <1> 	;	u.pgdir = page directory (physical) address
  2561                              <1> 	; OUTPUT ->
  2562                              <1> 	;	EDX = PDE address
  2563                              <1> 	;	EAX = page table address (physical)
  2564                              <1> 	;	;(CF=1 -> Invalid page address)
  2565                              <1> 	;
  2566                              <1> 	; Modified Registers -> EDX
  2567                              <1> 	;
  2568 00003010 89DA                <1> 	mov	edx, ebx
  2569 00003012 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2570 00003015 C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2571 00003018 0315[98710000]      <1> 	add	edx, [u.pgdir]
  2572                              <1> 	;
  2573 0000301E 21C0                <1> 	and	eax, eax
  2574 00003020 7506                <1> 	jnz	short spde_1
  2575                              <1> 	;
  2576 00003022 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2577                              <1> 	;test	al, 1
  2578                              <1> 	;jz	short spde_2
  2579 00003024 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2580                              <1> spde_1:
  2581                              <1> 	;and	cx, 0FFFh
  2582 00003028 8902                <1> 	mov	[edx], eax
  2583 0000302A 66090A              <1> 	or	[edx], cx
  2584 0000302D C3                  <1> 	retn
  2585                              <1> ;spde_2: ; error
  2586                              <1> ;	stc
  2587                              <1> ;	retn
  2588                              <1> 
  2589                              <1> set_pte:	; Set page table entry (PTE)
  2590                              <1> 	; 24/07/2015
  2591                              <1> 	; 20/07/2015
  2592                              <1> 	; 23/06/2015
  2593                              <1> 	; 18/04/2015
  2594                              <1> 	; 12/04/2015
  2595                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2596                              <1> 	;
  2597                              <1> 	; INPUT ->
  2598                              <1> 	;	EAX = physical page address
  2599                              <1> 	;	      (use present value if EAX = 0)
  2600                              <1> 	;	EBX = virtual (linear) address
  2601                              <1> 	;	ECX = page attributes (lower 12 bits)
  2602                              <1> 	;	      (higher 20 bits must be ZERO)
  2603                              <1> 	;	      (bit 0 must be 1)	 
  2604                              <1> 	;	u.pgdir = page directory (physical) address
  2605                              <1> 	; OUTPUT ->
  2606                              <1> 	;	EAX = physical page address
  2607                              <1> 	;	(EDX = PTE value)
  2608                              <1> 	;	EBX = virtual address
  2609                              <1> 	;
  2610                              <1> 	;	CF = 1 -> error
  2611                              <1> 	;
  2612                              <1> 	; Modified Registers -> EAX, EDX
  2613                              <1> 	;
  2614 0000302E 50                  <1> 	push	eax
  2615 0000302F A1[98710000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2616 00003034 E837000000          <1> 	call 	get_pde
  2617                              <1> 		; EDX = PDE address
  2618                              <1> 		; EAX = PDE value
  2619 00003039 5A                  <1> 	pop	edx ; physical page address
  2620 0000303A 722A                <1> 	jc	short spte_err ; PDE not present
  2621                              <1> 	;
  2622 0000303C 53                  <1> 	push	ebx ; 24/07/2015
  2623 0000303D 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2624                              <1> 			    ; EDX = PT address (physical)	
  2625 00003041 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2626 00003044 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2627                              <1> 			 ; clear higher 10 bits (PD bits)
  2628 0000304A C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2629 0000304D 01C3                <1> 	add	ebx, eax
  2630                              <1> 	;
  2631 0000304F 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2632 00003051 A801                <1> 	test	al, 1
  2633 00003053 740C                <1> 	jz	short spte_0
  2634 00003055 09D2                <1> 	or	edx, edx
  2635 00003057 750F                <1> 	jnz	short spte_1
  2636 00003059 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2637 0000305D 89C2                <1> 	mov	edx, eax
  2638 0000305F EB09                <1> 	jmp	short spte_2	
  2639                              <1> spte_0:
  2640                              <1> 	; If this PTE contains a swap (disk) address,
  2641                              <1> 	; it can be updated by using 'swap_in' procedure
  2642                              <1> 	; only!
  2643 00003061 21C0                <1> 	and	eax, eax
  2644 00003063 7403                <1> 	jz	short spte_1
  2645                              <1> 	; 24/07/2015
  2646                              <1> 	; swapped page ! (on disk)
  2647 00003065 5B                  <1> 	pop	ebx
  2648                              <1> spte_err:
  2649 00003066 F9                  <1> 	stc
  2650 00003067 C3                  <1> 	retn
  2651                              <1> spte_1: 
  2652 00003068 89D0                <1> 	mov	eax, edx
  2653                              <1> spte_2:
  2654 0000306A 09CA                <1> 	or	edx, ecx
  2655                              <1> 	; 23/06/2015
  2656 0000306C 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2657                              <1> 	; 24/07/2015
  2658 0000306E 5B                  <1> 	pop	ebx
  2659 0000306F C3                  <1> 	retn
  2660                              <1> 
  2661                              <1> get_pde:	; Get present value of the relevant PDE
  2662                              <1> 	; 20/07/2015
  2663                              <1> 	; 18/04/2015
  2664                              <1> 	; 12/04/2015
  2665                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2666                              <1> 	;
  2667                              <1> 	; INPUT ->
  2668                              <1> 	;	EBX = virtual (linear) address
  2669                              <1> 	;	EAX = page directory (physical) address
  2670                              <1> 	; OUTPUT ->
  2671                              <1> 	;	EDX = Page directory entry address
  2672                              <1> 	;	EAX = Page directory entry value
  2673                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2674                              <1> 	; Modified Registers -> EDX, EAX
  2675                              <1> 	;
  2676 00003070 89DA                <1> 	mov	edx, ebx
  2677 00003072 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2678 00003075 C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2679 00003078 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2680 0000307A 8B02                <1> 	mov	eax, [edx]
  2681 0000307C A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2682 0000307E 751F                <1> 	jnz	short gpte_retn
  2683 00003080 F9                  <1> 	stc
  2684                              <1> gpde_retn:	
  2685 00003081 C3                  <1> 	retn
  2686                              <1> 
  2687                              <1> get_pte:
  2688                              <1> 		; Get present value of the relevant PTE
  2689                              <1> 	; 29/07/2015
  2690                              <1> 	; 20/07/2015
  2691                              <1> 	; 18/04/2015
  2692                              <1> 	; 12/04/2015
  2693                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2694                              <1> 	;
  2695                              <1> 	; INPUT ->
  2696                              <1> 	;	EBX = virtual (linear) address
  2697                              <1> 	;	EAX = page directory (physical) address
  2698                              <1> 	; OUTPUT ->
  2699                              <1> 	;	EDX = Page table entry address (if CF=0)
  2700                              <1> 	;	      Page directory entry address (if CF=1)
  2701                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2702                              <1> 	;	EAX = Page table entry value (page address)
  2703                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2704                              <1> 	; Modified Registers -> EAX, EDX
  2705                              <1> 	;
  2706 00003082 E8E9FFFFFF          <1> 	call 	get_pde
  2707 00003087 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2708                              <1> 	;jnc	short gpte_1
  2709                              <1> 	;retn
  2710                              <1> ;gpte_1:
  2711 00003089 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2712 0000308D 89DA                <1> 	mov	edx, ebx
  2713 0000308F C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2714 00003092 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2715                              <1> 			 ; clear higher 10 bits (PD bits)
  2716 00003098 C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2717 0000309B 01C2                <1> 	add	edx, eax
  2718 0000309D 8B02                <1> 	mov	eax, [edx]
  2719                              <1> gpte_retn:
  2720 0000309F C3                  <1> 	retn
  2721                              <1> 
  2722                              <1> deallocate_page_dir:
  2723                              <1> 	; 15/09/2015
  2724                              <1> 	; 05/08/2015
  2725                              <1> 	; 30/04/2015
  2726                              <1> 	; 28/04/2015
  2727                              <1> 	; 17/10/2014
  2728                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2729                              <1> 	;
  2730                              <1> 	; INPUT ->
  2731                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2732                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2733                              <1> 	; OUTPUT ->
  2734                              <1> 	;	All of page tables in the page directory
  2735                              <1> 	;	and page dir's itself will be deallocated
  2736                              <1> 	;	except 'read only' duplicated pages (will be converted
  2737                              <1> 	;	to writable pages).
  2738                              <1> 	;
  2739                              <1> 	; Modified Registers -> EAX
  2740                              <1> 	;
  2741                              <1> 	;
  2742 000030A0 56                  <1> 	push	esi
  2743 000030A1 51                  <1> 	push	ecx
  2744 000030A2 50                  <1> 	push	eax
  2745 000030A3 89C6                <1> 	mov	esi, eax 
  2746 000030A5 31C9                <1> 	xor	ecx, ecx
  2747                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2748                              <1> 	; it must not be deallocated
  2749 000030A7 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2750                              <1> dapd_0:
  2751 000030A9 AD                  <1> 	lodsd
  2752 000030AA A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2753 000030AC 7409                <1> 	jz	short dapd_1	
  2754 000030AE 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2755 000030B2 E812000000          <1> 	call	deallocate_page_table			
  2756                              <1> dapd_1:
  2757 000030B7 41                  <1> 	inc	ecx ; page directory entry index
  2758 000030B8 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2759 000030BE 72E9                <1> 	jb	short dapd_0
  2760                              <1> dapd_2:
  2761 000030C0 58                  <1> 	pop	eax
  2762 000030C1 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2763 000030C6 59                  <1> 	pop	ecx
  2764 000030C7 5E                  <1> 	pop	esi
  2765 000030C8 C3                  <1> 	retn
  2766                              <1> 
  2767                              <1> deallocate_page_table:
  2768                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  2769                              <1> 	;	 (temporary modifications)
  2770                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2771                              <1> 	; 19/09/2015
  2772                              <1> 	; 15/09/2015
  2773                              <1> 	; 05/08/2015
  2774                              <1> 	; 30/04/2015
  2775                              <1> 	; 28/04/2015
  2776                              <1> 	; 24/10/2014
  2777                              <1> 	; 23/10/2014
  2778                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2779                              <1> 	;
  2780                              <1> 	; INPUT ->
  2781                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2782                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2783                              <1> 	;	(ECX = page directory entry index)
  2784                              <1> 	; OUTPUT ->
  2785                              <1> 	;	All of pages in the page table and page table's itself
  2786                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2787                              <1> 	;	(will be converted to writable pages).
  2788                              <1> 	;
  2789                              <1> 	; Modified Registers -> EAX
  2790                              <1> 	;
  2791 000030C9 56                  <1> 	push	esi
  2792 000030CA 57                  <1> 	push	edi
  2793 000030CB 52                  <1> 	push	edx
  2794 000030CC 50                  <1> 	push	eax ; *
  2795 000030CD 89C6                <1> 	mov	esi, eax 
  2796 000030CF 31FF                <1> 	xor	edi, edi ; 0
  2797                              <1> dapt_0:
  2798 000030D1 AD                  <1> 	lodsd
  2799 000030D2 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2800 000030D4 7455                <1> 	jz	short dapt_1
  2801                              <1> 	;
  2802 000030D6 A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2803                              <1> 				  ; (must be 1)
  2804 000030D8 753F                <1> 	jnz	short dapt_3
  2805                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2806 000030DA 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2807                              <1> 				   ; as child's page ?
  2808 000030DE 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2809                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2810                              <1> 	; ECX = page directory entry index (0-1023)
  2811 000030E0 53                  <1> 	push	ebx
  2812 000030E1 51                  <1> 	push	ecx
  2813 000030E2 66C1E102            <1> 	shl	cx, 2 ; *4 
  2814 000030E6 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2815 000030E8 8B0B                <1> 	mov	ecx, [ebx]
  2816 000030EA F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2817 000030ED 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2818 000030EF 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2819                              <1> 	; EDI = page table entry index (0-1023)
  2820 000030F4 89FA                <1> 	mov	edx, edi 
  2821 000030F6 66C1E202            <1> 	shl	dx, 2 ; *4 
  2822 000030FA 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2823 000030FC 8B1A                <1> 	mov	ebx, [edx]
  2824 000030FE F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2825 00003101 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2826 00003103 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2827 00003107 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2828 0000310C 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2829 0000310E 7507                <1> 	jne	short dapt_2	; not same page
  2830                              <1> 				; deallocate the child's page
  2831 00003110 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2832 00003113 59                  <1> 	pop	ecx
  2833 00003114 5B                  <1> 	pop	ebx
  2834 00003115 EB0D                <1> 	jmp	short dapt_4
  2835                              <1> 
  2836                              <1> ; 17/04/2021
  2837                              <1> ; ('dapt_1' is disabled as temporary)
  2838                              <1> ;
  2839                              <1> ;dapt_1:
  2840                              <1> ;	or	eax, eax	; swapped page ?
  2841                              <1> ;	jz	short dapt_5	; no
  2842                              <1> ;				; yes
  2843                              <1> ;	shr	eax, 1
  2844                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2845                              <1> ;				  ; on the swap disk (or in file)
  2846                              <1> ;	jmp	short dapt_5
  2847                              <1> dapt_2:
  2848 00003117 59                  <1> 	pop	ecx
  2849 00003118 5B                  <1> 	pop	ebx
  2850                              <1> dapt_3:	
  2851                              <1> 	; 12/07/2016
  2852 00003119 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2853 0000311D 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2854                              <1> 	;
  2855                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2856 0000311F E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2857                              <1> dapt_4:
  2858 00003124 C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2859                              <1> dapt_1:	; 17/04/2021 (temporary)
  2860                              <1> dapt_5:
  2861 0000312B 47                  <1> 	inc	edi ; page table entry index
  2862 0000312C 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2863 00003132 729D                <1> 	jb	short dapt_0
  2864                              <1> 	;
  2865 00003134 58                  <1> 	pop	eax ; *
  2866 00003135 5A                  <1> 	pop	edx
  2867 00003136 5F                  <1> 	pop	edi	
  2868 00003137 5E                  <1> 	pop	esi
  2869                              <1> 	;
  2870                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2871                              <1> 	;retn
  2872                              <1> 
  2873                              <1> deallocate_page:
  2874                              <1> 	; 15/09/2015
  2875                              <1> 	; 28/04/2015
  2876                              <1> 	; 10/03/2015
  2877                              <1> 	; 17/10/2014
  2878                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2879                              <1> 	;
  2880                              <1> 	; INPUT -> 
  2881                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2882                              <1> 	; OUTPUT ->
  2883                              <1> 	;	[free_pages] is increased
  2884                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2885                              <1> 	;	CF = 1 if the page is already deallocated
  2886                              <1> 	; 	       (or not allocated) before.  
  2887                              <1> 	;
  2888                              <1> 	; Modified Registers -> EAX
  2889                              <1> 	;
  2890 00003138 53                  <1> 	push	ebx
  2891 00003139 52                  <1> 	push	edx
  2892                              <1> 	;
  2893 0000313A C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2894                              <1> 				     ; 12 bits right
  2895                              <1> 				     ; to get page number
  2896 0000313D 89C2                <1> 	mov	edx, eax
  2897                              <1> 	; 15/09/2015
  2898 0000313F C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2899                              <1> 				     ; (1 allocation bit = 1 page)
  2900                              <1> 				     ; (1 allocation bytes = 8 pages)
  2901 00003142 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2902                              <1> 				     ; (to get 32 bit position)			
  2903                              <1> 	;
  2904 00003145 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2905 0000314A 01D3                <1> 	add	ebx, edx
  2906 0000314C 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2907                              <1> 				     ; (allocation bit position)	 
  2908 0000314F 3B15[44700000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2909                              <1> 				     ; than the address in 'next_page' ?
  2910                              <1> 				     ; (next/first free page value)		
  2911 00003155 7306                <1> 	jnb	short dap_1	     ; no	
  2912 00003157 8915[44700000]      <1> 	mov	[next_page], edx     ; yes
  2913                              <1> dap_1:
  2914 0000315D 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2915                              <1> 				     ; set relevant bit to 1.
  2916                              <1> 				     ; set CF to the previous bit value	
  2917                              <1> 	;cmc			     ; complement carry flag	
  2918                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2919                              <1> 				     ; if the page is already deallocated
  2920                              <1> 				     ; before.	
  2921 00003160 FF05[40700000]      <1>         inc     dword [free_pages]
  2922                              <1> dap_2:
  2923 00003166 5A                  <1> 	pop	edx
  2924 00003167 5B                  <1> 	pop	ebx
  2925 00003168 C3                  <1> 	retn
  2926                              <1> 
  2927                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2928                              <1> ;;                                                              ;;
  2929                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  2930                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  2931                              <1> ;;                                                              ;;
  2932                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2933                              <1> 
  2934                              <1> ;;$Revision: 5057 $
  2935                              <1> 
  2936                              <1> 
  2937                              <1> ;;align 4
  2938                              <1> ;;proc alloc_page
  2939                              <1> 
  2940                              <1> ;;        pushfd
  2941                              <1> ;;        cli
  2942                              <1> ;;        push    ebx
  2943                              <1> ;;;//-
  2944                              <1> ;;        cmp     [pg_data.pages_free], 1
  2945                              <1> ;;        jle     .out_of_memory
  2946                              <1> ;;;//-
  2947                              <1> ;;
  2948                              <1> ;;        mov     ebx, [page_start]
  2949                              <1> ;;        mov     ecx, [page_end]
  2950                              <1> ;;.l1:
  2951                              <1> ;;        bsf     eax, [ebx];
  2952                              <1> ;;        jnz     .found
  2953                              <1> ;;        add     ebx, 4
  2954                              <1> ;;        cmp     ebx, ecx
  2955                              <1> ;;        jb      .l1
  2956                              <1> ;;        pop     ebx
  2957                              <1> ;;        popfd
  2958                              <1> ;;        xor     eax, eax
  2959                              <1> ;;        ret
  2960                              <1> ;;.found:
  2961                              <1> ;;;//-
  2962                              <1> ;;        dec     [pg_data.pages_free]
  2963                              <1> ;;        jz      .out_of_memory
  2964                              <1> ;;;//-
  2965                              <1> ;;        btr     [ebx], eax
  2966                              <1> ;;        mov     [page_start], ebx
  2967                              <1> ;;        sub     ebx, sys_pgmap
  2968                              <1> ;;        lea     eax, [eax+ebx*8]
  2969                              <1> ;;        shl     eax, 12
  2970                              <1> ;;;//-       dec [pg_data.pages_free]
  2971                              <1> ;;        pop     ebx
  2972                              <1> ;;        popfd
  2973                              <1> ;;        ret
  2974                              <1> ;;;//-
  2975                              <1> ;;.out_of_memory:
  2976                              <1> ;;        mov     [pg_data.pages_free], 1
  2977                              <1> ;;        xor     eax, eax
  2978                              <1> ;;        pop     ebx
  2979                              <1> ;;        popfd
  2980                              <1> ;;        ret
  2981                              <1> ;;;//-
  2982                              <1> ;;endp
  2983                              <1> 
  2984                              <1> duplicate_page_dir:
  2985                              <1> 	; 21/09/2015
  2986                              <1> 	; 31/08/2015
  2987                              <1> 	; 20/07/2015
  2988                              <1> 	; 28/04/2015
  2989                              <1> 	; 27/04/2015
  2990                              <1> 	; 18/04/2015
  2991                              <1> 	; 12/04/2015
  2992                              <1> 	; 18/10/2014
  2993                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  2994                              <1> 	;
  2995                              <1> 	; INPUT -> 
  2996                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  2997                              <1> 	;		    page directory.
  2998                              <1> 	; OUTPUT ->
  2999                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3000                              <1> 	;	       page directory.
  3001                              <1> 	;	(New page directory with new page table entries.)
  3002                              <1> 	;	(New page tables with read only copies of the parent's
  3003                              <1> 	;	pages.)
  3004                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3005                              <1> 	;
  3006                              <1> 	; Modified Registers -> none (except EAX)
  3007                              <1> 	;
  3008 00003169 E802FEFFFF          <1> 	call	allocate_page
  3009 0000316E 723E                <1> 	jc	short dpd_err
  3010                              <1> 	;
  3011 00003170 55                  <1> 	push	ebp ; 20/07/2015
  3012 00003171 56                  <1> 	push	esi
  3013 00003172 57                  <1> 	push	edi
  3014 00003173 53                  <1> 	push	ebx
  3015 00003174 51                  <1> 	push	ecx
  3016 00003175 8B35[98710000]      <1> 	mov	esi, [u.pgdir]
  3017 0000317B 89C7                <1> 	mov	edi, eax
  3018 0000317D 50                  <1> 	push	eax ; save child's page directory address
  3019                              <1> 	; 31/08/2015
  3020                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3021                              <1> 	; (use same system space for all user page tables) 
  3022 0000317E A5                  <1> 	movsd
  3023 0000317F BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3024 00003184 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3025                              <1> dpd_0:	
  3026 00003189 AD                  <1> 	lodsd
  3027                              <1> 	;or	eax, eax
  3028                              <1>         ;jnz     short dpd_1
  3029 0000318A A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3030 0000318C 7508                <1> 	jnz	short dpd_1
  3031                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3032 0000318E 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3033 00003194 EB0F                <1> 	jmp	short dpd_2
  3034                              <1> dpd_1:	
  3035 00003196 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3036 0000319A 89C3                <1> 	mov	ebx, eax
  3037                              <1> 	; EBX = Parent's page table address
  3038 0000319C E81F000000          <1> 	call	duplicate_page_table
  3039 000031A1 720C                <1> 	jc	short dpd_p_err
  3040                              <1> 	; EAX = Child's page table address
  3041 000031A3 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3042                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3043                              <1> 			 ; (present, writable, user)
  3044                              <1> dpd_2:
  3045 000031A5 AB                  <1> 	stosd
  3046 000031A6 E2E1                <1> 	loop	dpd_0
  3047                              <1> 	;
  3048 000031A8 58                  <1> 	pop	eax  ; restore child's page directory address
  3049                              <1> dpd_3:
  3050 000031A9 59                  <1> 	pop	ecx
  3051 000031AA 5B                  <1> 	pop	ebx
  3052 000031AB 5F                  <1> 	pop	edi
  3053 000031AC 5E                  <1> 	pop	esi
  3054 000031AD 5D                  <1> 	pop	ebp ; 20/07/2015
  3055                              <1> dpd_err:
  3056 000031AE C3                  <1> 	retn
  3057                              <1> dpd_p_err:
  3058                              <1> 	; release the allocated pages missing (recover free space)
  3059 000031AF 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3060 000031B0 8B1D[98710000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3061 000031B6 E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3062 000031BB 29C0                <1> 	sub	eax, eax ; 0
  3063 000031BD F9                  <1> 	stc
  3064 000031BE EBE9                <1> 	jmp	short dpd_3	
  3065                              <1> 
  3066                              <1> duplicate_page_table:
  3067                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3068                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3069                              <1> 	;	 (temporary modifications)
  3070                              <1> 	; 16/04/2021 (Retro UNIX 386 v2)
  3071                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3072                              <1> 	; 21/09/2015
  3073                              <1> 	; 20/07/2015
  3074                              <1> 	; 05/05/2015
  3075                              <1> 	; 28/04/2015
  3076                              <1> 	; 27/04/2015
  3077                              <1> 	; 18/04/2015
  3078                              <1> 	; 18/10/2014
  3079                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3080                              <1> 	;
  3081                              <1> 	; INPUT -> 
  3082                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3083                              <1> 	;       20/02/2017		 
  3084                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3085                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3086                              <1> 	; OUTPUT ->
  3087                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3088                              <1> 	;	      (with 'read only' attribute of page table entries)
  3089                              <1> 	;	20/02/2017
  3090                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3091                              <1> 	;	
  3092                              <1> 	;	CF = 1 -> error 
  3093                              <1> 	;
  3094                              <1> 	; Modified Registers -> EBP (except EAX)
  3095                              <1> 	;
  3096 000031C0 E8ABFDFFFF          <1> 	call	allocate_page
  3097 000031C5 725B                <1> 	jc	short dpt_err
  3098                              <1> 	;
  3099 000031C7 50                  <1> 	push	eax ; *
  3100 000031C8 56                  <1> 	push	esi
  3101 000031C9 57                  <1> 	push	edi
  3102 000031CA 52                  <1> 	push	edx
  3103 000031CB 51                  <1> 	push	ecx
  3104                              <1> 	;
  3105 000031CC 89DE                <1> 	mov	esi, ebx
  3106 000031CE 89C7                <1> 	mov	edi, eax
  3107 000031D0 89C2                <1> 	mov	edx, eax
  3108 000031D2 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3109                              <1> dpt_0:
  3110 000031D8 AD                  <1> 	lodsd
  3111 000031D9 21C0                <1> 	and	eax, eax
  3112 000031DB 7435                <1> 	jz	short dpt_3
  3113 000031DD A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3114                              <1> 	; 17/04/2021 (temporary)
  3115 000031DF 7503                <1> 	jnz	short dpt_1
  3116                              <1> 	;jz	short dpt_p_err
  3117                              <1> 	; 31/12/2021
  3118 000031E1 F9                  <1> 	stc
  3119 000031E2 EB39                <1> 	jmp	short dpt_p_err
  3120                              <1> 
  3121                              <1> ; 17/04/2021
  3122                              <1> ; ('reload_page' procedure call is disabled as temporary)
  3123                              <1> ;
  3124                              <1> ;	; 20/07/2015
  3125                              <1> ;	; ebp = virtual (linear) address of the memory page
  3126                              <1> ;	call	reload_page ; 28/04/2015
  3127                              <1> ;	jc	short dpt_p_err
  3128                              <1> dpt_1:
  3129                              <1> 	; 21/09/2015
  3130 000031E4 89C1                <1> 	mov	ecx, eax
  3131 000031E6 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3132 000031EA F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3133 000031ED 751A                <1> 	jnz	short dpt_2
  3134                              <1> 	; Read only (parent) page
  3135                              <1> 	; 	- there is a third process which uses this page -
  3136                              <1> 	; Allocate a new page for the child process
  3137 000031EF E87CFDFFFF          <1> 	call	allocate_page
  3138 000031F4 7227                <1> 	jc	short dpt_p_err
  3139 000031F6 57                  <1> 	push	edi
  3140 000031F7 56                  <1> 	push	esi
  3141 000031F8 89CE                <1> 	mov	esi, ecx
  3142 000031FA 89C7                <1> 	mov	edi, eax
  3143 000031FC B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3144 00003201 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3145 00003203 5E                  <1> 	pop	esi
  3146 00003204 5F                  <1> 	pop	edi
  3147                              <1> 	;
  3148                              <1> 
  3149                              <1> ; 17/04/2021
  3150                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  3151                              <1> ; 
  3152                              <1> ;	push	ebx
  3153                              <1> ;	push	eax
  3154                              <1> ;	; 20/07/2015
  3155                              <1> ;	mov	ebx, ebp
  3156                              <1> ;	; ebx = virtual (linear) address of the memory page
  3157                              <1> ;	call	add_to_swap_queue
  3158                              <1> ;	pop	eax
  3159                              <1> ;	pop	ebx
  3160                              <1> 
  3161                              <1> 	; 21/09/2015
  3162 00003205 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3163                              <1> 		; user + writable + present page
  3164 00003207 EB09                <1> 	jmp	short dpt_3
  3165                              <1> dpt_2:
  3166                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3167 00003209 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3168                              <1> 		    ; (read only page!)
  3169 0000320B 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3170 0000320E 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3171                              <1> dpt_3:
  3172 00003212 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3173                              <1> 	;
  3174 00003213 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3175                              <1> 	;
  3176 00003219 39D7                <1> 	cmp	edi, edx
  3177 0000321B 72BB                <1> 	jb	short dpt_0
  3178                              <1> dpt_p_err:
  3179 0000321D 59                  <1> 	pop	ecx
  3180 0000321E 5A                  <1> 	pop	edx
  3181 0000321F 5F                  <1> 	pop	edi
  3182 00003220 5E                  <1> 	pop	esi
  3183 00003221 58                  <1> 	pop	eax ; *
  3184                              <1> dpt_err:
  3185 00003222 C3                  <1> 	retn
  3186                              <1> 
  3187                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3188                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2
  3189                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  3190                              <1> 	;	 (temporary modifications)
  3191                              <1> 	; 21/09/2015
  3192                              <1> 	; 19/09/2015
  3193                              <1> 	; 17/09/2015
  3194                              <1> 	; 28/08/2015
  3195                              <1> 	; 20/07/2015
  3196                              <1> 	; 28/06/2015
  3197                              <1> 	; 03/05/2015
  3198                              <1> 	; 30/04/2015
  3199                              <1> 	; 18/04/2015
  3200                              <1> 	; 12/04/2015
  3201                              <1> 	; 30/10/2014
  3202                              <1> 	; 11/09/2014
  3203                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3204                              <1> 	;
  3205                              <1> 	; Note: This is not an interrupt/exception handler.
  3206                              <1> 	;	This is a 'page fault remedy' subroutine 
  3207                              <1> 	;	which will be called by standard/uniform
  3208                              <1> 	;	exception handler.
  3209                              <1> 	;
  3210                              <1> 	; INPUT -> 
  3211                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3212                              <1> 	;
  3213                              <1> 	;	cr2 = the virtual (linear) address 
  3214                              <1> 	;	      which has caused to page fault (19/09/2015)
  3215                              <1> 	;
  3216                              <1> 	; OUTPUT ->
  3217                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3218                              <1> 	;	EAX = 0 -> no error
  3219                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3220                              <1> 	;
  3221                              <1> 	; Modified Registers -> none (except EAX)
  3222                              <1> 	;	
  3223                              <1>         ;
  3224                              <1>         ; ERROR CODE:
  3225                              <1> 	;	 31  .....	4   3	2   1	0
  3226                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3227                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3228                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3229                              <1> 	;
  3230                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3231                              <1>     	;		a page-protection violation. When not set,
  3232                              <1> 	;		it was caused by a non-present page.
  3233                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3234                              <1> 	;		a page write. When not set, it was caused
  3235                              <1> 	;		by a page read.
  3236                              <1> 	; U : USER    -	When set, the page fault was caused 
  3237                              <1> 	;		while CPL = 3. 
  3238                              <1> 	;		This does not necessarily mean that
  3239                              <1> 	;		the page fault was a privilege violation.
  3240                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3241                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3242                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3243                              <1> 	;     FETCH	an instruction fetch
  3244                              <1> 	;
  3245                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3246                              <1> 	;  31               22                  12 11                    0
  3247                              <1> 	; +-------------------+-------------------+-----------------------+
  3248                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3249                              <1>        	; +-------------------+-------------------+-----------------------+
  3250                              <1> 	;
  3251                              <1> 
  3252                              <1> 	;; CR3 REGISTER (Control Register 3)
  3253                              <1> 	;  31                                   12             5 4 3 2   0
  3254                              <1> 	; +---------------------------------------+-------------+---+-----+
  3255                              <1>       	; |                                       |  		|P|P|     |
  3256                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3257                              <1>       	; |                                       | 		|D|T|     |
  3258                              <1>    	; +---------------------------------------+-------------+---+-----+
  3259                              <1> 	;
  3260                              <1> 	;	PWT    - WRITE THROUGH
  3261                              <1> 	;	PCD    - CACHE DISABLE		
  3262                              <1> 	;
  3263                              <1> 	;
  3264                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3265                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3266                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3267                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3268                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3269                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3270                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3271                              <1> 	;
  3272                              <1>         ;       P      - PRESENT
  3273                              <1>         ;       R/W    - READ/WRITE
  3274                              <1>         ;       U/S    - USER/SUPERVISOR
  3275                              <1> 	;	PWT    - WRITE THROUGH
  3276                              <1> 	;	PCD    - CACHE DISABLE	
  3277                              <1> 	;	A      - ACCESSED	
  3278                              <1>         ;       D      - DIRTY (IGNORED)
  3279                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3280                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3281                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3282                              <1> 	;
  3283                              <1> 	;
  3284                              <1> 	;; x86 PAGE TABLE 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|P|U|R| |
  3288                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3289                              <1>       	; |                                       |     | |T| | |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
  3299                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3300                              <1> 	;	G      - GLOBAL	 
  3301                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3302                              <1> 	;
  3303                              <1> 	;
  3304                              <1> 	;; 80386 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>       	; |                                       |     | | | | | | |U|R| |
  3308                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3309                              <1>       	; |                                       |     | | | | | | |S|W| |
  3310                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3311                              <1> 	;
  3312                              <1>         ;       P      - PRESENT
  3313                              <1>         ;       R/W    - READ/WRITE
  3314                              <1>         ;       U/S    - USER/SUPERVISOR
  3315                              <1>         ;       D      - DIRTY
  3316                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3317                              <1> 	;
  3318                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3319                              <1> 	;
  3320                              <1> 	;
  3321                              <1> 	;; Invalid Page Table Entry
  3322                              <1> 	; 31                                                           1 0
  3323                              <1>       	; +-------------------------------------------------------------+-+
  3324                              <1>       	; |                                                             | |
  3325                              <1>       	; |                          AVAILABLE                          |0|
  3326                              <1>       	; |                                                             | |
  3327                              <1>       	; +-------------------------------------------------------------+-+
  3328                              <1> 	;
  3329                              <1> 
  3330 00003223 53                  <1> 	push	ebx
  3331 00003224 52                  <1> 	push	edx
  3332 00003225 51                  <1> 	push	ecx
  3333                              <1> 	;
  3334                              <1> 	; 21/09/2015 (debugging)
  3335 00003226 FF05[B0710000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3336 0000322C FF05[34760000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3337                              <1> 	; 28/06/2015
  3338                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3339 00003232 8A15[2C760000]      <1> 	mov	dl, [error_code]
  3340                              <1> 	;
  3341 00003238 F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3342                              <1> 			; sign
  3343 0000323B 7416                <1> 	jz	short pfh_alloc_np
  3344                              <1> 	; 
  3345                              <1> 	; If it is not a 'write on read only page' type page fault
  3346                              <1> 	; major page fault error with minor reason must be returned without 
  3347                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3348                              <1> 	; after return here!
  3349                              <1> 	; Page fault will be remedied, by copying page contents
  3350                              <1> 	; to newly allocated page with write permission;
  3351                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3352                              <1> 	; used for working with minimum possible memory usage. 
  3353                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3354                              <1> 	; process with 'read only' flag. If the child process attempts to
  3355                              <1> 	; write on these read only pages, page fault will be directed here
  3356                              <1> 	; for allocating a new page with same data/content. 
  3357                              <1> 	;
  3358                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3359                              <1> 	; will not force to separate CODE and DATA space 
  3360                              <1> 	; in a process/program... 
  3361                              <1> 	; CODE segment/section may contain DATA!
  3362                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3363                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3364                              <1> 	;	
  3365 0000323D F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3366                              <1> 			; sign
  3367 00003240 744F                <1>         jz	short pfh_p_err
  3368                              <1> 	; 31/08/2015
  3369 00003242 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3370                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3371 00003245 744A                <1>         jz	short pfh_pv_err
  3372                              <1> 	;
  3373                              <1> 	; make a new page and copy the parent's page content
  3374                              <1> 	; as the child's new page content
  3375                              <1> 	;
  3376 00003247 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3377                              <1> 			 ; which has caused to page fault
  3378 0000324A E87C000000          <1> 	call 	copy_page
  3379 0000324F 7239                <1>         jc	short pfh_im_err ; insufficient memory
  3380                              <1> 	;
  3381 00003251 EB72                <1>         jmp     pfh_cpp_ok
  3382                              <1> 	;
  3383                              <1> pfh_alloc_np:
  3384 00003253 E818FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3385 00003258 7230                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3386                              <1> pfh_chk_cpl:
  3387                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3388                              <1> 		; (Lower 12 bits are ZERO, because 
  3389                              <1> 		;	the address is on a page boundary)
  3390 0000325A 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3391 0000325D 7505                <1> 	jnz	short pfh_um
  3392                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3393 0000325F 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3394                              <1> 			 ; of the current/active page directory
  3395                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3396                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3397 00003262 EB06                <1> 	jmp	short pfh_get_pde
  3398                              <1> 	;
  3399                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3400 00003264 8B1D[98710000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3401                              <1> 			; Physical address of the USER's page directory
  3402                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3403                              <1> pfh_get_pde:
  3404 0000326A 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3405 0000326D 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3406                              <1> 			 ; which has been caused to page fault
  3407                              <1> 			 ;
  3408 00003270 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3409 00003273 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3410                              <1> 	;
  3411 00003276 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3412 00003278 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3413 0000327A F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3414 0000327D 741A                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3415                              <1> 			  	  ; set/validate page directory entry
  3416 0000327F 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3417 00003284 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3418 00003286 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3419 00003288 EB25                <1> 	jmp	short pfh_get_pte
  3420                              <1> 
  3421                              <1> 	; 31/12/2021 (short jump)
  3422                              <1> pfh_im_err:
  3423 0000328A B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3424                              <1> 			; Major (Primary) Error: Page Fault
  3425                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3426 0000328F EB36                <1> 	jmp	short pfh_err_retn
  3427                              <1> 
  3428                              <1> 	; 31/12/2021
  3429                              <1> pfh_p_err: ; 09/03/2015
  3430                              <1> pfh_pv_err:
  3431                              <1> 	; Page fault was caused by a protection-violation
  3432 00003291 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3433                              <1> 			; Major (Primary) Error: Page Fault
  3434                              <1> 			; Minor (Secondary) Error: Protection violation !
  3435 00003296 F9                  <1> 	stc
  3436 00003297 EB2E                <1> 	jmp	short pfh_err_retn
  3437                              <1> 
  3438                              <1> pfh_set_pde:
  3439                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3440                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3441                              <1> 	;
  3442 00003299 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3443 0000329B 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3444 0000329D 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3445 0000329F 89C3                <1> 	mov	ebx, eax
  3446 000032A1 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3447 000032A6 72E2                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3448                              <1> pfh_spde_1:
  3449                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3450 000032A8 89C1                <1> 	mov	ecx, eax
  3451 000032AA E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3452                              <1> pfh_get_pte:
  3453 000032AF 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3454                              <1> 			 ; which has been caused to page fault
  3455 000032B2 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3456 000032B4 C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3457                              <1> 			 ; higher 20 bits of the page fault address 
  3458 000032B7 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3459 000032BC C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3460 000032BF 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3461                              <1> ; 17/04/2021 temporary
  3462                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3463                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3464                              <1> ; 17/04/2021
  3465                              <1> ; ('swap_in' procedure call has been disabled as temporary)
  3466                              <1> ;
  3467                              <1> ;	and	eax, eax
  3468                              <1> ;	jz	short pfh_gpte_1
  3469                              <1> ;	; 20/07/2015
  3470                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3471                              <1> ;	push	ebp ; 20/07/2015
  3472                              <1> ;	mov	ebp, cr2
  3473                              <1> ;		; ECX = physical address of the page table entry
  3474                              <1> ;		; EBX = Memory page address (physical!)
  3475                              <1> ;		; EAX = Swap disk (offset) address
  3476                              <1> ;		; EBP = virtual address (page fault address)
  3477                              <1> ;	call	swap_in
  3478                              <1> ;	pop	ebp
  3479                              <1> ;	jc      short pfh_err_retn
  3480                              <1> ;	xchg	ecx, ebx
  3481                              <1> ;		; EBX = physical address of the page table entry
  3482                              <1> ;		; ECX = new page
  3483                              <1> pfh_gpte_1:
  3484 000032C1 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3485 000032C3 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3486                              <1> pfh_cpp_ok:
  3487                              <1> ; 17/04/2021
  3488                              <1> ; ('add_to_swap_queue' procedure call has been disabled as temporary)
  3489                              <1> ;
  3490                              <1> ;	; 20/07/2015
  3491                              <1> ;	mov	ebx, cr2
  3492                              <1> ;	call 	add_to_swap_queue
  3493                              <1> 	;
  3494                              <1> 	; The new PTE (which contains the new page) will be added to 
  3495                              <1> 	; the swap queue, here. 
  3496                              <1> 	; (Later, if memory will become insufficient, 
  3497                              <1> 	; one page will be swapped out which is at the head of 
  3498                              <1> 	; the swap queue by using FIFO and access check methods.)
  3499                              <1> 	;
  3500 000032C5 31C0                <1> 	xor	eax, eax  ; 0
  3501                              <1> 	;
  3502                              <1> pfh_err_retn:
  3503 000032C7 59                  <1> 	pop	ecx
  3504 000032C8 5A                  <1> 	pop	edx
  3505 000032C9 5B                  <1> 	pop	ebx
  3506 000032CA C3                  <1> 	retn 
  3507                              <1> 	
  3508                              <1> copy_page:
  3509                              <1> 	; 16/04/2021
  3510                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3511                              <1> 	; 22/09/2015
  3512                              <1> 	; 21/09/2015
  3513                              <1> 	; 19/09/2015
  3514                              <1> 	; 07/09/2015
  3515                              <1> 	; 31/08/2015
  3516                              <1> 	; 20/07/2015
  3517                              <1> 	; 05/05/2015
  3518                              <1> 	; 03/05/2015
  3519                              <1> 	; 18/04/2015
  3520                              <1> 	; 12/04/2015
  3521                              <1> 	; 30/10/2014
  3522                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3523                              <1> 	;
  3524                              <1> 	; INPUT -> 
  3525                              <1> 	;	EBX = Virtual (linear) address of source page
  3526                              <1> 	;	     (Page fault address)
  3527                              <1> 	; OUTPUT ->
  3528                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3529                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3530                              <1> 	;	EAX = 0 (CF = 1) 
  3531                              <1> 	;		if there is not a free page to be allocated
  3532                              <1> 	;	(page content of the source page will be copied
  3533                              <1> 	;	onto the target/new page) 	
  3534                              <1> 	;
  3535                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3536                              <1> 	;
  3537                              <1> 
  3538                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3539                              <1> 	; INPUT: 
  3540                              <1> 	;	EBX = Virtual (linear) address of source page
  3541                              <1> 	;	     (Page fault address)
  3542                              <1> 	; OUTPUT:
  3543                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3544                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3545                              <1> 	;	EAX = 0 (CF = 1) 
  3546                              <1> 	;		if there is not a free page to be allocated
  3547                              <1> 	;	(page content of the source page will be copied
  3548                              <1> 	;	onto the target/new page) 	
  3549                              <1> 	;
  3550                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3551                              <1> 	
  3552 000032CB 56                  <1> 	push	esi ; *
  3553 000032CC 57                  <1> 	push	edi ; **
  3554                              <1> 	; 16/04/2021
  3555                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3556                              <1> 	;push	ebx ; ***
  3557                              <1> 	;push	ecx ; ****
  3558 000032CD 31F6                <1> 	xor 	esi, esi
  3559 000032CF C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3560 000032D2 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3561 000032D4 C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3562 000032D7 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3563 000032DA 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3564 000032DC 031D[98710000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3565 000032E2 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3566 000032E4 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3567 000032E8 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3568 000032EA 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3569 000032F0 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3570 000032F4 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3571                              <1> 	; 07/09/2015
  3572 000032F6 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3573                              <1> 				     ; read only page as a child process?)	
  3574 000032FB 7509                <1> 	jnz	short cpp_0 ; yes
  3575 000032FD 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3576 000032FF 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3577 00003304 EB32                <1> 	jmp	short cpp_1
  3578                              <1> cpp_0:
  3579 00003306 89FE                <1> 	mov	esi, edi
  3580 00003308 0335[9C710000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3581 0000330E 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3582 00003310 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3583 00003314 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3584 00003316 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3585 0000331C 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3586 00003320 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3587 00003322 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3588                              <1> 	; 21/09/2015
  3589 00003324 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3590 00003326 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3591                              <1> 	;
  3592 0000332A F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3593 0000332D 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3594                              <1> 	;
  3595 0000332F 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3596 00003334 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3597 00003336 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3598                              <1> 			    ; Convert child's page to writable page
  3599                              <1> cpp_1:
  3600 00003338 E833FCFFFF          <1> 	call	allocate_page
  3601 0000333D 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3602 0000333F 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3603 00003341 7405                <1> 	jz	short cpp_2
  3604                              <1> 		; Convert read only page to writable page 
  3605                              <1> 		;(for the parent of the current process)
  3606                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3607                              <1> 	; 22/09/2015
  3608 00003343 890E                <1> 	mov	[esi], ecx
  3609 00003345 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3610                              <1> 				 ; 1+2+4 = 7
  3611                              <1> cpp_2:
  3612 00003348 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3613                              <1> 	; 07/09/2015
  3614 0000334A 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3615 0000334C B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3616 00003351 F3A5                <1> 	rep	movsd ; 31/08/2015
  3617                              <1> cpp_3:		
  3618 00003353 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3619 00003355 8903                <1> 	mov	[ebx], eax ; Update PTE
  3620 00003357 28C0                <1> 	sub	al, al ; clear attributes
  3621                              <1> cpp_4:
  3622                              <1> 	; 16/04/2021
  3623                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3624                              <1> 	;pop	ecx ; ****
  3625                              <1> 	;pop	ebx ; ***
  3626 00003359 5F                  <1> 	pop	edi ; **
  3627 0000335A 5E                  <1> 	pop	esi ; *
  3628 0000335B C3                  <1> 	retn
  3629                              <1> 
  3630                              <1> ;; 28/04/2015
  3631                              <1> ;; 24/10/2014
  3632                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3633                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3634                              <1> ;;
  3635                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3636                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3637                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3638                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3639                              <1> ;;
  3640                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3641                              <1> ;;
  3642                              <1> ;; Method:
  3643                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3644                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3645                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3646                              <1> ;;	When a new page is being allocated, swap queue is updated
  3647                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3648                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3649                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3650                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3651                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3652                              <1> ;;	offset value becomes it's previous offset value - 4.
  3653                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3654                              <1> ;;	the queue/list is not shifted.
  3655                              <1> ;;	After the queue/list shift, newly allocated page is added
  3656                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3657                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3658                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3659                              <1> ;;	
  3660                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3661                              <1> ;;	the first non-accessed, writable page in the list, 
  3662                              <1> ;;	from the head to the tail. The list is shifted to left 
  3663                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3664                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3665                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3666                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3667                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3668                              <1> ;;	procedure will be failed)...
  3669                              <1> ;;
  3670                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3671                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3672                              <1> ;;	(PTE) will be added to the tail of the queue after
  3673                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3674                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3675                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3676                              <1> ;;
  3677                              <1> ;;
  3678                              <1> ;;	
  3679                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3680                              <1> ;;
  3681                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3682                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3683                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3684                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3685                              <1> ;;
  3686                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3687                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3688                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3689                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3690                              <1> ;; 		 (entire swap space must be accessed by using
  3691                              <1> ;;		 31 bit offset address) 
  3692                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3693                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3694                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3695                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3696                              <1> ;;
  3697                              <1> ;; 					
  3698                              <1> ;; Method:
  3699                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3700                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3701                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3702                              <1> ;;	Swapping out is performed by using swap page queue.
  3703                              <1> ;;
  3704                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3705                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3706                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3707                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3708                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3709                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3710                              <1> ;;	calculated by adding offset value to the swap partition's 
  3711                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3712                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3713                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3714                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3715                              <1> ;;	is in a partitioned virtual hard disk.) 
  3716                              <1> ;;
  3717                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3718                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3719                              <1> ;;
  3720                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3721                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3722                              <1> ;;
  3723                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3724                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3725                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3726                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3727                              <1> ;;	it means relevant (respective) block is in use, and, 
  3728                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3729                              <1> ;;      swap disk/file block is free.
  3730                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3731                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3732                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3733                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3734                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3735                              <1> ;;	------------------------------------------------------------
  3736                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3737                              <1> ;;	------------------------------------------------------------
  3738                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3739                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3740                              <1> ;;
  3741                              <1> ;;	..............................................................
  3742                              <1> ;;
  3743                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3744                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3745                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3746                              <1> ;;	position with value of 1 on the table is converted to swap
  3747                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3748                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3749                              <1> ;;	number of physical swap disk or virtual swap disk)
  3750                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3751                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3752                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3753                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3754                              <1> ;;	If disk write procedure returns with error or free count of 
  3755                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3756                              <1> ;;	'insufficient memory error' (cf=1). 
  3757                              <1> ;;
  3758                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3759                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3760                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3761                              <1> ;;	free blocks after a disk write error. It will return to 
  3762                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3763                              <1> ;;
  3764                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3765                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3766                              <1> ;;	address (cf=0). 
  3767                              <1> ;;
  3768                              <1> ;;	..............................................................
  3769                              <1> ;;
  3770                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3771                              <1> ;;	file sectors at specified memory page. Then page allocation
  3772                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3773                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3774                              <1> ;;	to do, except to terminate the process which is the owner of
  3775                              <1> ;;	the swapped page.
  3776                              <1> ;;
  3777                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3778                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3779                              <1> ;;	updates [swpd_first] pointer if it is required.
  3780                              <1> ;;
  3781                              <1> ;;	..............................................................	 
  3782                              <1> ;;
  3783                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3784                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3785                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3786                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3787                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3788                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3789                              <1> ;;
  3790                              <1> 
  3791                              <1> ; 17/04/2021
  3792                              <1> ; ('swap_in' procedure call is disabled as temporary)
  3793                              <1> 
  3794                              <1> ; 30/11/2021 - temporary !
  3795                              <1> ;swap_in:
  3796                              <1> 	; 31/08/2015
  3797                              <1> 	; 20/07/2015
  3798                              <1> 	; 28/04/2015
  3799                              <1> 	; 18/04/2015
  3800                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3801                              <1> 	;
  3802                              <1> 	; INPUT -> 
  3803                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3804                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3805                              <1> 	;	EAX = Offset Address for the swapped page on the
  3806                              <1> 	;	      swap disk or in the swap file.
  3807                              <1> 	;
  3808                              <1> 	; OUTPUT ->
  3809                              <1> 	;	EAX = 0 if loading at memory has been successful
  3810                              <1> 	;
  3811                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3812                              <1> 	;		  or sector not present or drive not ready
  3813                              <1> 	;	     EAX = Error code
  3814                              <1> 	;	     [u.error] = EAX 
  3815                              <1> 	;		       = The last error code for the process
  3816                              <1> 	;		         (will be reset after returning to user)	  
  3817                              <1> 	;
  3818                              <1> 	; Modified Registers -> EAX
  3819                              <1> 	;
  3820                              <1> 
  3821                              <1> ;       cmp     dword [swp_drv], 0
  3822                              <1> ;	jna	short swpin_dnp_err
  3823                              <1> ;
  3824                              <1> ;	cmp	eax, [swpd_size]
  3825                              <1> ;	jnb	short swpin_snp_err
  3826                              <1> ;
  3827                              <1> ;	push	esi
  3828                              <1> ;	push	ebx
  3829                              <1> ;	push	ecx
  3830                              <1> ;	mov	esi, [swp_drv]	
  3831                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3832                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3833                              <1> ;		; size different than 512 bytes, logical disk sector
  3834                              <1> ;		; size is 512 bytes and disk reading procedure
  3835                              <1> ;		; will be performed for reading 4096 bytes
  3836                              <1> ;		; (2*2048, 8*512). 
  3837                              <1> ;	; ESI = Logical disk description table address
  3838                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3839                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3840                              <1> ;	; ECX = Sector count ; 8 sectors
  3841                              <1> ;	push	eax
  3842                              <1> ;	call	logical_disk_read
  3843                              <1> ;	pop	eax
  3844                              <1> ;	jnc	short swpin_read_ok
  3845                              <1> ;	;
  3846                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3847                              <1> ;	mov	[u.error], eax
  3848                              <1> ;	jmp	short swpin_retn
  3849                              <1> ;	;
  3850                              <1> ;swpin_read_ok:
  3851                              <1> ;	; EAX = Offset address (logical sector number)
  3852                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3853                              <1> ;	;
  3854                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3855                              <1> ;	; 20/07/2015
  3856                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3857                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3858                              <1> ;	mov	bl, [u.uno] ; current process number
  3859                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3860                              <1> ;	call	swap_queue_shift
  3861                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3862                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3863                              <1> ;	; zf = 1
  3864                              <1> ;swpin_retn:
  3865                              <1> ;	pop	ecx
  3866                              <1> ;	pop	ebx
  3867                              <1> ;	pop	esi
  3868                              <1> ;	retn
  3869                              <1> ;
  3870                              <1> ;swpin_dnp_err:
  3871                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3872                              <1> ;swpin_err_retn:
  3873                              <1> ;	mov	[u.error], eax
  3874                              <1> ;	stc
  3875                              <1> ;	retn
  3876                              <1> ;
  3877                              <1> ;swpin_snp_err:
  3878                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3879                              <1> ;	jmp	short swpin_err_retn
  3880                              <1> 
  3881                              <1> ; 17/04/2021
  3882                              <1> ; ('swap_out' procedure call is disabled as temporary)
  3883                              <1> 
  3884                              <1> ; 30/11/2021 - temporary !
  3885                              <1> ;swap_out:
  3886                              <1> 	; 10/06/2016
  3887                              <1> 	; 07/06/2016
  3888                              <1>         ; 23/05/2016
  3889                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3890                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3891                              <1> 	;
  3892                              <1> 	; INPUT -> 
  3893                              <1> 	;	none
  3894                              <1> 	;
  3895                              <1> 	; OUTPUT ->
  3896                              <1> 	;	EAX = Physical page address (which is swapped out
  3897                              <1> 	;	      for allocating a new page)
  3898                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3899                              <1> 	;		  or sector not present or drive not ready
  3900                              <1> 	;	     EAX = Error code
  3901                              <1> 	;	     [u.error] = EAX 
  3902                              <1> 	;		       = The last error code for the process
  3903                              <1> 	;		         (will be reset after returning to user)	  
  3904                              <1> 	;
  3905                              <1> 	; Modified Registers -> none (except EAX)
  3906                              <1> 	;
  3907                              <1> 
  3908                              <1> ;	cmp 	word [swpq_count], 1
  3909                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3910                              <1> ;
  3911                              <1> ;       ;cmp    dword [swp_drv], 1
  3912                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3913                              <1> ;
  3914                              <1> ;       cmp     dword [swpd_free], 1
  3915                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3916                              <1> ;
  3917                              <1> ;	push	ebx ; *
  3918                              <1> ;swpout_1:
  3919                              <1> ;	; 10/06/2016
  3920                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3921                              <1> ;	call	swap_queue_shift
  3922                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3923                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3924                              <1> ;				       ; pointer in the swap queue
  3925                              <1> ;	; EAX = PTE value of the page
  3926                              <1> ;	; EBX = PTE address of the page
  3927                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3928                              <1> ;	;
  3929                              <1> ;	; 07/06/2016
  3930                              <1> ;	; 19/05/2016
  3931                              <1> ;	; check this page is in timer events or not
  3932                              <1> ;	
  3933                              <1> ;swpout_timer_page_0:
  3934                              <1> ;	push	edx ; **
  3935                              <1> ;
  3936                              <1> ;	; 07/06/2016
  3937                              <1> ;	cmp	byte [timer_events], 0 
  3938                              <1> ;	jna	short swpout_2
  3939                              <1> ;	;
  3940                              <1> ;	mov	dl, [timer_events]
  3941                              <1> ;
  3942                              <1> ;	push	ecx ; ***
  3943                              <1> ;	push	ebx ; ****
  3944                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  3945                              <1> ;			       ; structures 
  3946                              <1> ;swpout_timer_page_1:
  3947                              <1> ;	mov	cl, [ebx]
  3948                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  3949                              <1> ;	jz	short swpout_timer_page_3
  3950                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  3951                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  3952                              <1> ;				; of the response byte address, to
  3953                              <1> ;				; get beginning of the page address)
  3954                              <1> ;	cmp	eax, ecx
  3955                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  3956                              <1> ;	
  3957                              <1> ;	; !same page!
  3958                              <1> ;	;
  3959                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  3960                              <1> ;	; This page will be used by the kernel to put timer event
  3961                              <1> ;	; response (signal return) byte at the requested address;
  3962                              <1> ;	; in order to prevent a possible wrong write (while
  3963                              <1> ;	; this page is swapped out) on physical memory,
  3964                              <1> ;	; we must protect this page against to be swapped out!
  3965                              <1> ;	;
  3966                              <1> ;	pop	ebx ; ****
  3967                              <1> ;	pop	ecx ; ***
  3968                              <1> ;	pop	edx ; **
  3969                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  3970                              <1> ; 
  3971                              <1> ;swpout_timer_page_2:
  3972                              <1> ;	; 07/06/2016
  3973                              <1> ;	dec	dl
  3974                              <1> ;	jz	short swpout_timer_page_4
  3975                              <1> ;swpout_timer_page_3:
  3976                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  3977                              <1> ;	;jnb	short swpout_timer_page_4
  3978                              <1> ;	add	ebx, 16
  3979                              <1> ;	jmp	short swpout_timer_page_1	
  3980                              <1> ;
  3981                              <1> ;swpout_timer_page_4:
  3982                              <1> ;	pop	ebx ; ****
  3983                              <1> ;	pop	ecx ; ***
  3984                              <1> ;swpout_2:
  3985                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  3986                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  3987                              <1> ;	;
  3988                              <1> ;	call	link_swap_block
  3989                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  3990                              <1> ;				       ; because [swpd_free] value
  3991                              <1> ;				       ; was checked at the beginging. 	
  3992                              <1> ;	pop	edx ; **
  3993                              <1> ;	pop	ebx ; *
  3994                              <1> ;	jmp	short swpout_nfspc_err 
  3995                              <1> ;swpout_3:
  3996                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  3997                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  3998                              <1> ;	;	
  3999                              <1> ;	push	esi ; **
  4000                              <1> ;	push	ecx ; ***
  4001                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4002                              <1> ;	mov	esi, [swp_drv]	
  4003                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4004                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4005                              <1> ;		; size different than 512 bytes, logical disk sector
  4006                              <1> ;		; size is 512 bytes and disk writing procedure
  4007                              <1> ;		; will be performed for writing 4096 bytes
  4008                              <1> ;		; (2*2048, 8*512). 
  4009                              <1> ;	; ESI = Logical disk description table address
  4010                              <1> ;	; EBX = Buffer (Page) address
  4011                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4012                              <1> ;	; ECX = Sector count ; 8 sectors
  4013                              <1> ;	; edx = PTE address
  4014                              <1> ;	call	logical_disk_write
  4015                              <1> ;	; edx = PTE address
  4016                              <1> ;	pop	ecx ; sector address	
  4017                              <1> ;	jnc	short swpout_write_ok
  4018                              <1> ;	;
  4019                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4020                              <1> ;swpout_dw_err:
  4021                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4022                              <1> ;	mov	[u.error], eax
  4023                              <1> ;	jmp	short swpout_retn
  4024                              <1> ;	;
  4025                              <1> ;swpout_write_ok:
  4026                              <1> ;	; EBX = Buffer (page) address
  4027                              <1> ;	; EDX = Page Table Entry address
  4028                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4029                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4030                              <1> ;	mov 	[edx], ecx 
  4031                              <1> ;		; bit 0 = 0 (swapped page)
  4032                              <1> ;	mov	eax, ebx
  4033                              <1> ;swpout_retn:
  4034                              <1> ;	pop	ecx ; ***
  4035                              <1> ;	pop	esi ; **
  4036                              <1> ;	pop	ebx ; *
  4037                              <1> ;	retn
  4038                              <1> ;
  4039                              <1> ;;swpout_dnp_err:
  4040                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4041                              <1> ;;	jmp	short swpout_err_retn
  4042                              <1> ;swpout_nfspc_err:
  4043                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4044                              <1> ;swpout_err_retn:
  4045                              <1> ;	mov	[u.error], eax
  4046                              <1> ;	;stc
  4047                              <1> ;	retn
  4048                              <1> ;swpout_npts_err:
  4049                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4050                              <1> ;	pop	ebx
  4051                              <1> ;	jmp	short swpout_err_retn
  4052                              <1> ;swpout_im_err:
  4053                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4054                              <1> ;	jmp	short swpout_err_retn
  4055                              <1> 
  4056                              <1> ; 17/04/2021
  4057                              <1> ; ('swap_queue_shift' procedure call is disabled as temporary)
  4058                              <1> 
  4059                              <1> ; 30/11/2021 - temporary !
  4060                              <1> ;swap_queue_shift:
  4061                              <1> 	; 26/03/2017
  4062                              <1> 	; 10/06/2016
  4063                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4064                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4065                              <1> 	;
  4066                              <1> 	; INPUT ->
  4067                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4068                              <1> 	;	      and process number combination (bit 0 to 11)
  4069                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4070                              <1> 	;	
  4071                              <1> 	; OUTPUT ->
  4072                              <1> 	;	If EBX input > 0 
  4073                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4074                              <1> 	; 	   from the tail to the head, up to entry offset
  4075                              <1> 	; 	   which points to EBX input value or nothing
  4076                              <1> 	;	   to do if EBX value is not found on the queue.
  4077                              <1> 	;	   (The entry -with EBX value- will be removed
  4078                              <1> 	;	   from the queue if it is found.)
  4079                              <1> 	;
  4080                              <1> 	;	   EAX = 0		
  4081                              <1> 	;
  4082                              <1> 	;	If EBX input = 0
  4083                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4084                              <1> 	; 	   from the tail to the head, if the PTE address
  4085                              <1> 	;	   which is pointed in head of the queue is marked
  4086                              <1> 	;	   as "accessed" or it is marked as "non present".
  4087                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4088                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4089                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4090                              <1> 	;	   -without dropping pointer of the PTE from 
  4091                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4092                              <1> 	;	   Pointer in the head will be moved into the tail,
  4093                              <1> 	;	   other PTEs will be shifted on head direction.)
  4094                              <1> 	;
  4095                              <1> 	;	   Swap queue will be shifted up to the first
  4096                              <1> 	;	   'present' or 'non accessed' page will be found
  4097                              <1> 	;	   (as pointed) on the queue head (then it will be
  4098                              <1>         ;          removed/dropped from the queue).
  4099                              <1> 	;
  4100                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4101                              <1> 	;		 (it's pointer -virtual address-) dropped
  4102                              <1> 	;		 (removed) from swap queue.
  4103                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4104                              <1> 	;	         which is (it's pointer -virtual address-)
  4105                              <1> 	;		 dropped (removed) from swap queue.
  4106                              <1> 	;
  4107                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4108                              <1> 	;
  4109                              <1> 	; Modified Registers -> EAX, EBX
  4110                              <1> 	;
  4111                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4112                              <1> ;	and	ax, ax
  4113                              <1> ;	jz	short swpqs_retn
  4114                              <1> ;	push	edi
  4115                              <1> ;	push	esi
  4116                              <1> ;	push	ecx
  4117                              <1> ;	mov	esi, swap_queue
  4118                              <1> ;	mov	ecx, eax
  4119                              <1> ;	or	ebx, ebx
  4120                              <1> ;	jz	short swpqs_7
  4121                              <1> ;swpqs_1:
  4122                              <1> ;	lodsd
  4123                              <1> ;	cmp	eax, ebx
  4124                              <1> ;	je	short swpqs_2
  4125                              <1> ;	loop	swpqs_1
  4126                              <1> ;	; 10/06/2016
  4127                              <1> ;	sub	eax, eax 
  4128                              <1> ;	jmp	short swpqs_6
  4129                              <1> ;swpqs_2:
  4130                              <1> ;	mov	edi, esi
  4131                              <1> ;	sub 	edi, 4
  4132                              <1> ;swpqs_3:
  4133                              <1> ;	dec	word [swpq_count]
  4134                              <1> ;	jz	short swpqs_5
  4135                              <1> ;swpqs_4:
  4136                              <1> ;	dec 	ecx
  4137                              <1> ;	rep	movsd	; shift up (to the head)
  4138                              <1> ;swpqs_5:
  4139                              <1> ;	xor	eax, eax
  4140                              <1> ;	mov	[edi], eax
  4141                              <1> ;swpqs_6:
  4142                              <1> ;	pop	ecx
  4143                              <1> ;	pop	esi
  4144                              <1> ;	pop	edi
  4145                              <1> ;swpqs_retn:
  4146                              <1> ;	retn		
  4147                              <1> ;swpqs_7:
  4148                              <1> ;	mov	edi, esi ; head
  4149                              <1> ;	lodsd
  4150                              <1> ;	; 20/07/2015
  4151                              <1> ;	mov	ebx, eax
  4152                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4153                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4154                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4155                              <1> ;		      ; ax = process number (1 to 4095)
  4156                              <1> ;	cmp	al, [u.uno]
  4157                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4158                              <1> ;	jne	short swpqs_8
  4159                              <1> ;	mov	eax, [u.pgdir]
  4160                              <1> ;	jmp	short swpqs_9
  4161                              <1> ;swpqs_8:
  4162                              <1> ;	; 09/06/2016
  4163                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4164                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4165                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4166                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4167                              <1> ;
  4168                              <1> ;	;shl	ax, 2
  4169                              <1> ;	shl	al, 2
  4170                              <1> ;	mov 	eax, [eax+p.upage-4]
  4171                              <1> ;	or	eax, eax
  4172                              <1> ;	jz	short swpqs_3 ; invalid upage
  4173                              <1> ;	add	eax, u.pgdir - user
  4174                              <1> ;			 ; u.pgdir value for the process
  4175                              <1> ;			 ; is in [eax]
  4176                              <1> ;	mov	eax, [eax]
  4177                              <1> ;	and	eax, eax
  4178                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4179                              <1> ;swpqs_9:
  4180                              <1> ;	push	edx
  4181                              <1> ;	; eax = page directory
  4182                              <1> ;	; ebx = virtual address
  4183                              <1> ;	call	get_pte
  4184                              <1> ;	mov	ebx, edx	; PTE address
  4185                              <1> ;	pop	edx
  4186                              <1> ;	; 10/06/2016
  4187                              <1> ;	jc	short swpqs_13 ; empty PDE
  4188                              <1> ;	; EAX = PTE value
  4189                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4190                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4191                              <1> ;			        ; from the queue (head)
  4192                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4193                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4194                              <1> ;			        ; from the queue (head) 	
  4195                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4196                              <1> ;	;jnz	short swpqs_11  ; present
  4197                              <1> ;			        ; accessed page
  4198                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4199                              <1> ;	jc	short swpqs_11  ; accessed page
  4200                              <1> ;
  4201                              <1> ;	dec	ecx
  4202                              <1> ;	mov	[swpq_count], cx
  4203                              <1> ;       jz      short swpqs_10
  4204                              <1> ;		; esi = head + 4
  4205                              <1> ;		; edi = head
  4206                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4207                              <1> ;swpqs_10:
  4208                              <1> ;	mov	[edi], ecx ; 0
  4209                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4210                              <1> ;
  4211                              <1> ;swpqs_11:
  4212                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4213                              <1> ;	; Rotation (head -> tail)
  4214                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4215                              <1> ;	jz	short swpqs_10
  4216                              <1> ;		; esi = head + 4
  4217                              <1> ;		; edi = head
  4218                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4219                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4220                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4221                              <1> ;
  4222                              <1> ;	mov	cx, [swpq_count]
  4223                              <1> ;
  4224                              <1> ;swpqs_12:
  4225                              <1> ;	mov	esi, swap_queue ; head
  4226                              <1> ;       jmp     swpqs_7
  4227                              <1> ;
  4228                              <1> ;swpqs_13:
  4229                              <1> ;	dec	ecx
  4230                              <1> ;	mov	[swpq_count], cx
  4231                              <1> ;       jz      swpqs_5
  4232                              <1> ;	jmp	short swpqs_12
  4233                              <1> 
  4234                              <1> ; 17/04/2021
  4235                              <1> ; ('add_to_swp_queue' procedure call is disabled as temporary)
  4236                              <1> 
  4237                              <1> ; 30/11/2021 - temporary !
  4238                              <1> ;add_to_swap_queue:
  4239                              <1> 	; 20/02/2017
  4240                              <1> 	; 20/07/2015
  4241                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4242                              <1> 	;
  4243                              <1> 	; Adds new page to swap queue
  4244                              <1> 	; (page directories and page tables must not be added
  4245                              <1> 	; to swap queue)	
  4246                              <1> 	;
  4247                              <1> 	; INPUT ->
  4248                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4249                              <1> 	;	[u.uno]
  4250                              <1> 	;	20/02/2017
  4251                              <1> 	;	(Linear address = CORE + user's virtual address)
  4252                              <1> 	;
  4253                              <1> 	; OUTPUT ->
  4254                              <1> 	;	EAX = [swpq_count]
  4255                              <1> 	;	      (after the PTE has been added)
  4256                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4257                              <1> 	;	      the PTE could not be added.
  4258                              <1> 	;
  4259                              <1> 	; Modified Registers -> EAX
  4260                              <1> 	;
  4261                              <1> ;	push	ebx
  4262                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4263                              <1> ;	mov	bl, [u.uno] ; current process number
  4264                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4265                              <1> ;				 ; it is already on the queue
  4266                              <1> ;		; then add it to the tail of the queue
  4267                              <1> ;	movzx	eax, word [swpq_count]
  4268                              <1> ;	cmp	ax, 1024
  4269                              <1> ;	jb	short atsq_1
  4270                              <1> ;	sub	ax, ax
  4271                              <1> ;	pop	ebx
  4272                              <1> ;	retn
  4273                              <1> ;atsq_1:
  4274                              <1> ;	push	esi
  4275                              <1> ;	mov	esi, swap_queue
  4276                              <1> ;	and	ax, ax
  4277                              <1> ;	jz	short atsq_2
  4278                              <1> ;	shl	ax, 2	; convert to offset
  4279                              <1> ;	add	esi, eax
  4280                              <1> ;	shr	ax, 2
  4281                              <1> ;atsq_2:
  4282                              <1> ;	inc	ax
  4283                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4284                              <1> ;	mov	[swpq_count], ax
  4285                              <1> ;	pop	esi
  4286                              <1> ;	pop	ebx
  4287                              <1> ;	retn
  4288                              <1> 
  4289                              <1> ; 17/04/2021
  4290                              <1> ; ('unlink_swap_block' procedure call is disabled as temporary)
  4291                              <1> 
  4292                              <1> ; 30/11/2021 - temporary !
  4293                              <1> ;unlink_swap_block:
  4294                              <1> 	; 15/09/2015
  4295                              <1> 	; 30/04/2015
  4296                              <1> 	; 18/04/2015
  4297                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4298                              <1> 	;
  4299                              <1> 	; INPUT -> 
  4300                              <1> 	;	EAX = swap disk/file offset address
  4301                              <1> 	;	      (bit 1 to bit 31)
  4302                              <1> 	; OUTPUT ->
  4303                              <1> 	;	[swpd_free] is increased
  4304                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4305                              <1> 	;
  4306                              <1> 	; Modified Registers -> EAX
  4307                              <1> 	;
  4308                              <1> ;	push	ebx
  4309                              <1> ;	push	edx
  4310                              <1> ;	;
  4311                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4312                              <1> ;				     ; 3 bits right
  4313                              <1> ;				     ; to get swap block/page number
  4314                              <1> ;	mov	edx, eax
  4315                              <1> ;	; 15/09/2015
  4316                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4317                              <1> ;				     ; (1 allocation bit = 1 page)
  4318                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4319                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4320                              <1> ;				     ; (to get 32 bit position)			
  4321                              <1> ;	;
  4322                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4323                              <1> ;	add	ebx, edx
  4324                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4325                              <1> ;				     ; (allocation bit position)	 
  4326                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4327                              <1> ;				     ; than the address in 'swpd_next' ?
  4328                              <1> ;				     ; (next/first free block value)		
  4329                              <1> ;	jnb	short uswpbl_1	     ; no	
  4330                              <1> ;	mov	[swpd_next], eax     ; yes	
  4331                              <1> ;uswpbl_1:
  4332                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4333                              <1> ;				     ; set relevant bit to 1.
  4334                              <1> ;				     ; set CF to the previous bit value	
  4335                              <1> ;	cmc			     ; complement carry flag	
  4336                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4337                              <1> ;				     ; if the block is already deallocated
  4338                              <1> ;				     ; before.	
  4339                              <1> ;       inc     dword [swpd_free]
  4340                              <1> ;uswpbl_2:
  4341                              <1> ;	pop	edx
  4342                              <1> ;	pop	ebx
  4343                              <1> ;	retn
  4344                              <1> 
  4345                              <1> ; 17/04/2021
  4346                              <1> ; ('link_swap_block' procedure call is disabled as temporary)
  4347                              <1> 
  4348                              <1> ; 30/11/2021 - temporary !
  4349                              <1> ;link_swap_block:
  4350                              <1> 	; 01/07/2015
  4351                              <1> 	; 18/04/2015
  4352                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4353                              <1> 	;
  4354                              <1> 	; INPUT -> none
  4355                              <1> 	;
  4356                              <1> 	; OUTPUT ->
  4357                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4358                              <1> 	;	      in sectors (corresponding 
  4359                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4360                              <1> 	;
  4361                              <1> 	;	CF = 1 and EAX = 0 
  4362                              <1> 	; 		   if there is not a free block to be allocated	
  4363                              <1> 	;
  4364                              <1> 	; Modified Registers -> none (except EAX)
  4365                              <1> 	;
  4366                              <1> 
  4367                              <1> ;	;mov	eax, [swpd_free]
  4368                              <1> ;	;and	eax, eax
  4369                              <1> ;	;jz	short out_of_swpspc
  4370                              <1> ;	;
  4371                              <1> ;	push	ebx
  4372                              <1> ;	push	ecx
  4373                              <1> ;	;
  4374                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4375                              <1> ;	mov	ecx, ebx
  4376                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4377                              <1> ;				 ; next_free_swap_block >> 5
  4378                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4379                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4380                              <1> ;lswbl_scan:
  4381                              <1> ;	cmp	ebx, ecx
  4382                              <1> ;	ja	short lswbl_notfound
  4383                              <1> ;	;
  4384                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4385                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4386                              <1> ;			   ; loads the destination with an index to
  4387                              <1> ;			   ; first set bit. (0 -> 31) 
  4388                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4389                              <1> ;	; 01/07/2015
  4390                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4391                              <1> ;			 ;
  4392                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4393                              <1> ;			 ;	  with value of 1 means 
  4394                              <1> ;			 ;	  the corresponding page is free 
  4395                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4396                              <1> ;	add	ebx, 4
  4397                              <1> ;			 ; We return back for searching next page block
  4398                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4399                              <1> ;			 ;	 we always will find at least 1 free block here.
  4400                              <1> ;	jmp    	short lswbl_scan
  4401                              <1> ;	;
  4402                              <1> ;lswbl_notfound:	
  4403                              <1> ;	sub	ecx, swap_alloc_table
  4404                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4405                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4406                              <1> ;	xor	eax, eax
  4407                              <1> ;	mov	[swpd_free], eax
  4408                              <1> ;	stc
  4409                              <1> ;lswbl_ok:
  4410                              <1> ;	pop	ecx
  4411                              <1> ;	pop	ebx
  4412                              <1> ;	retn
  4413                              <1> ;	;
  4414                              <1> ;;out_of_swpspc:
  4415                              <1> ;;	stc
  4416                              <1> ;;	retn
  4417                              <1> ;
  4418                              <1> ;lswbl_found:
  4419                              <1> ;	mov	ecx, ebx
  4420                              <1> ;	sub	ecx, swap_alloc_table
  4421                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4422                              <1> ;				 ; address/offset (to the next)
  4423                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4424                              <1> ;	;
  4425                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4426                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4427                              <1> ;				 ; in the destination.
  4428                              <1> ;				 ;
  4429                              <1> ;				 ; Reset the bit which is corresponding to the 
  4430                              <1> ;				 ; (just) allocated block.
  4431                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4432                              <1> ;	add	eax, ecx	 ; = block number
  4433                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4434                              <1> ;				 ; 1 block =  8 sectors
  4435                              <1> ;	;
  4436                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4437                              <1> ;	;
  4438                              <1> ;	; NOTE: The relevant page table entry will be updated
  4439                              <1> ;	;       according to this EAX value...
  4440                              <1> ;	;
  4441                              <1> ;	jmp	short lswbl_ok
  4442                              <1> 
  4443                              <1> ; 17/04/2021
  4444                              <1> ; ('logical_disk_read' procedure call is disabled as temporary)
  4445                              <1> 
  4446                              <1> ; 30/11/2021 - temporary !
  4447                              <1> ;logical_disk_read:
  4448                              <1> 	; 20/07/2015
  4449                              <1> 	; 09/03/2015 (temporary code here)
  4450                              <1> 	;
  4451                              <1> 	; INPUT ->
  4452                              <1> 	; 	ESI = Logical disk description table address
  4453                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4454                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4455                              <1> 	; 	ECX = Sector count
  4456                              <1> 	;
  4457                              <1> 	;
  4458                              <1> ;	retn
  4459                              <1> 
  4460                              <1> ; 17/04/2021
  4461                              <1> ; ('logical_disk_write' procedure call is disabled as temporary)
  4462                              <1> 
  4463                              <1> ; 30/11/2021 - temporary !
  4464                              <1> ;logical_disk_write:
  4465                              <1> 	; 20/07/2015
  4466                              <1> 	; 09/03/2015 (temporary code here)
  4467                              <1> 	;
  4468                              <1> 	; INPUT ->
  4469                              <1> 	; 	ESI = Logical disk description table address
  4470                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4471                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4472                              <1> 	; 	ECX = Sector count
  4473                              <1> 	;
  4474                              <1> ;	retn
  4475                              <1> 
  4476                              <1> get_physical_addr:
  4477                              <1> 	; 17/04/2021 - Retro UNIX 386 v2
  4478                              <1> 	;	(temporary modifications)
  4479                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4480                              <1> 	; 18/10/2015
  4481                              <1> 	; 29/07/2015
  4482                              <1> 	; 20/07/2015
  4483                              <1> 	; 04/06/2015
  4484                              <1> 	; 20/05/2015
  4485                              <1> 	; 28/04/2015
  4486                              <1> 	; 18/04/2015
  4487                              <1> 	; Get physical address
  4488                              <1> 	;     (allocates a new page for user if it is not present)
  4489                              <1> 	;	
  4490                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4491                              <1> 	; (buffer) address to physical address (of the buffer).)
  4492                              <1> 	; ('sys write', 'sys read' system calls...)
  4493                              <1> 	;
  4494                              <1> 	; INPUT ->
  4495                              <1> 	;	EBX = virtual address
  4496                              <1> 	;	u.pgdir = page directory (physical) address
  4497                              <1> 	;
  4498                              <1> 	; OUTPUT ->
  4499                              <1> 	;	EAX = physical address 
  4500                              <1> 	;	EBX = linear address	
  4501                              <1> 	;	EDX = physical address of the page frame
  4502                              <1> 	;	      (with attribute bits)
  4503                              <1> 	;	ECX = byte count within the page frame
  4504                              <1> 	;
  4505                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4506                              <1> 	;
  4507                              <1> 
  4508                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4509 0000335C A1[98710000]        <1> 	mov	eax, [u.pgdir]
  4510                              <1> 
  4511                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4512                              <1> 	
  4513 00003361 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4514                              <1> 	;
  4515                              <1> 	;mov	eax, [u.pgdir]
  4516 00003367 E816FDFFFF          <1> 	call	get_pte
  4517                              <1> 		; EDX = Page table entry address (if CF=0)
  4518                              <1> 	        ;       Page directory entry address (if CF=1)
  4519                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4520                              <1> 		; EAX = Page table entry value (page address)
  4521                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4522 0000336C 731C                <1> 	jnc	short gpa_1
  4523                              <1> 	;
  4524 0000336E E8FDFBFFFF          <1> 	call	allocate_page
  4525 00003373 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4526                              <1> gpa_0:
  4527 00003375 E867FCFFFF          <1> 	call 	clear_page
  4528                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4529 0000337A 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4530                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4531                              <1> 			   ; (user, writable, present page)	
  4532 0000337C 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4533 0000337E A1[98710000]        <1> 	mov	eax, [u.pgdir]	
  4534 00003383 E8FAFCFFFF          <1> 	call	get_pte
  4535 00003388 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4536                              <1> gpa_1:
  4537                              <1> 	; EAX = PTE value, EDX = PTE address
  4538 0000338A A801                <1> 	test 	al, PTE_A_PRESENT
  4539 0000338C 750A                <1> 	jnz	short gpa_3
  4540 0000338E 09C0                <1> 	or	eax, eax
  4541 00003390 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4542                              <1> 
  4543                              <1> ; 17/04/2021
  4544                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4545 00003392 EB2C                <1> 	jmp	short gpa_im_err  ; temporary !
  4546                              <1> 
  4547                              <1> 	; 20/07/2015
  4548                              <1> ;	push	ebp
  4549                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4550                              <1> ;	; reload swapped page
  4551                              <1> ;	call	reload_page ; 28/04/2015
  4552                              <1> ;	pop	ebp
  4553                              <1> ;	jc	short gpa_retn
  4554                              <1> gpa_2:
  4555                              <1> ; 17/04/2021
  4556                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)
  4557                              <1> 
  4558                              <1> 	; 20/07/2015
  4559                              <1> 	; 20/05/2015
  4560                              <1> 	; add this page to swap queue
  4561                              <1> ;	push	eax 
  4562                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4563                              <1> ;	call 	add_to_swap_queue
  4564                              <1> ;	pop	eax
  4565                              <1> 		; PTE address in EDX
  4566                              <1> 		; virtual address in EBX
  4567                              <1> 
  4568                              <1> 	; EAX = memory page address
  4569 00003394 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4570                              <1> 				  ; present flag, bit 0 = 1
  4571                              <1> 				  ; user flag, bit 2 = 1	
  4572                              <1> 				  ; writable flag, bit 1 = 1
  4573 00003396 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4574                              <1> gpa_3:
  4575                              <1> 	; 18/10/2015
  4576 00003398 89D9                <1> 	mov	ecx, ebx
  4577 0000339A 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4578 000033A0 89C2                <1> 	mov 	edx, eax
  4579 000033A2 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4580 000033A6 01C8                <1> 	add	eax, ecx
  4581 000033A8 F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4582 000033AA 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4583 000033B0 F8                  <1> 	clc
  4584                              <1> gpa_retn:
  4585 000033B1 C3                  <1> 	retn	
  4586                              <1> gpa_4:	
  4587 000033B2 E8B9FBFFFF          <1> 	call	allocate_page
  4588 000033B7 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4589 000033B9 E823FCFFFF          <1> 	call	clear_page
  4590 000033BE EBD4                <1> 	jmp	short gpa_2
  4591                              <1> 
  4592                              <1> gpa_im_err:	
  4593 000033C0 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4594                              <1> 				  ; Major error = 0 (No protection fault)	
  4595 000033C5 C3                  <1> 	retn
  4596                              <1> 
  4597                              <1> ; 17/04/2021
  4598                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4599                              <1> 
  4600                              <1> ; 30/11/2021 - temporary !
  4601                              <1> ;reload_page:
  4602                              <1> 	; 20/07/2015
  4603                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4604                              <1> 	;
  4605                              <1> 	; Reload (Restore) swapped page at memory
  4606                              <1> 	;
  4607                              <1> 	; INPUT -> 
  4608                              <1> 	;	EBP = Virtual (linear) memory address
  4609                              <1> 	;	EAX = PTE value (swap disk sector address)
  4610                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4611                              <1> 	; OUTPUT ->
  4612                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4613                              <1> 	;
  4614                              <1> 	;	CF = 1 and EAX = error code
  4615                              <1> 	;
  4616                              <1> 	; Modified Registers -> none (except EAX)
  4617                              <1> 	;
  4618                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4619                              <1> ;	push	ebx      ;
  4620                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4621                              <1> ;	call	allocate_page
  4622                              <1> ;	jc	short rlp_im_err
  4623                              <1> ;	xchg 	eax, ebx	
  4624                              <1> ;	; EBX = Physical memory (page) address
  4625                              <1> ;	; EAX = Swap disk (offset) address
  4626                              <1> ;	; EBP = Virtual (linear) memory address
  4627                              <1> ;	call	swap_in
  4628                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4629                              <1> ;	mov	eax, ebx	
  4630                              <1> ;rlp_retn:
  4631                              <1> ;	pop	ebx
  4632                              <1> ;	retn
  4633                              <1> ;	
  4634                              <1> ;rlp_im_err:	
  4635                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4636                              <1> ;				  ; Major error = 0 (No protection fault)	
  4637                              <1> ;	jmp	short rlp_retn
  4638                              <1> ;
  4639                              <1> ;rlp_swp_err:
  4640                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4641                              <1> ;	jmp	short rlp_retn
  4642                              <1> 
  4643                              <1> copy_page_dir:
  4644                              <1> 	; 17/04/2021 (temporary modifications)
  4645                              <1> 	; 19/09/2015
  4646                              <1> 	; temporary - 07/09/2015
  4647                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4648                              <1> 	;
  4649                              <1> 	; INPUT -> 
  4650                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4651                              <1> 	;		    page directory.
  4652                              <1> 	; OUTPUT ->
  4653                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4654                              <1> 	;	       page directory.
  4655                              <1> 	;	(New page directory with new page table entries.)
  4656                              <1> 	;	(New page tables with read only copies of the parent's
  4657                              <1> 	;	pages.)
  4658                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4659                              <1> 	;
  4660                              <1> 	; Modified Registers -> none (except EAX)
  4661                              <1> 	;
  4662 000033C6 E8A5FBFFFF          <1> 	call	allocate_page
  4663 000033CB 723E                <1> 	jc	short cpd_err
  4664                              <1> 	;
  4665 000033CD 55                  <1> 	push	ebp ; 20/07/2015
  4666 000033CE 56                  <1> 	push	esi
  4667 000033CF 57                  <1> 	push	edi
  4668 000033D0 53                  <1> 	push	ebx
  4669 000033D1 51                  <1> 	push	ecx
  4670 000033D2 8B35[98710000]      <1> 	mov	esi, [u.pgdir]
  4671 000033D8 89C7                <1> 	mov	edi, eax
  4672 000033DA 50                  <1> 	push	eax ; save child's page directory address
  4673                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4674                              <1> 	; (use same system space for all user page tables) 
  4675 000033DB A5                  <1> 	movsd
  4676 000033DC BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4677 000033E1 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4678                              <1> cpd_0:	
  4679 000033E6 AD                  <1> 	lodsd
  4680                              <1> 	;or	eax, eax
  4681                              <1>         ;jnz	short cpd_1
  4682 000033E7 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4683 000033E9 7508                <1> 	jnz	short cpd_1
  4684                              <1>  	; (virtual address at the end of the page table)	
  4685 000033EB 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4686 000033F1 EB0F                <1> 	jmp	short cpd_2
  4687                              <1> cpd_1:	
  4688 000033F3 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4689 000033F7 89C3                <1> 	mov	ebx, eax
  4690                              <1> 	; EBX = Parent's page table address
  4691 000033F9 E81F000000          <1> 	call	copy_page_table
  4692 000033FE 720C                <1> 	jc	short cpd_p_err
  4693                              <1> 	; EAX = Child's page table address
  4694 00003400 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4695                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4696                              <1> 			 ; (present, writable, user)
  4697                              <1> cpd_2:
  4698 00003402 AB                  <1> 	stosd
  4699 00003403 E2E1                <1> 	loop	cpd_0
  4700                              <1> 	;
  4701 00003405 58                  <1> 	pop	eax  ; restore child's page directory address
  4702                              <1> cpd_3:
  4703 00003406 59                  <1> 	pop	ecx
  4704 00003407 5B                  <1> 	pop	ebx
  4705 00003408 5F                  <1> 	pop	edi
  4706 00003409 5E                  <1> 	pop	esi
  4707 0000340A 5D                  <1> 	pop	ebp
  4708                              <1> cpd_err:
  4709 0000340B C3                  <1> 	retn
  4710                              <1> cpd_p_err:
  4711                              <1> 	; release the allocated pages missing (recover free space)
  4712 0000340C 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4713 0000340D 8B1D[98710000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4714 00003413 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4715 00003418 29C0                <1> 	sub	eax, eax ; 0
  4716 0000341A F9                  <1> 	stc
  4717 0000341B EBE9                <1> 	jmp	short cpd_3	
  4718                              <1> 
  4719                              <1> copy_page_table:
  4720                              <1> 	; 17/04/2021 (temporary modifications)
  4721                              <1> 	; 19/09/2015
  4722                              <1> 	; temporary - 07/09/2015
  4723                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4724                              <1> 	;
  4725                              <1> 	; INPUT -> 
  4726                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4727                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4728                              <1> 	; OUTPUT ->
  4729                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4730                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4731                              <1> 	;	CF = 1 -> error 
  4732                              <1> 	;
  4733                              <1> 	; Modified Registers -> EBP (except EAX)
  4734                              <1> 	;
  4735 0000341D E84EFBFFFF          <1> 	call	allocate_page
  4736 00003422 7244                <1> 	jc	short cpt_err
  4737                              <1> 	;
  4738 00003424 50                  <1> 	push	eax ; *
  4739                              <1> 	;push 	ebx
  4740 00003425 56                  <1> 	push	esi
  4741 00003426 57                  <1> 	push	edi
  4742 00003427 52                  <1> 	push	edx
  4743 00003428 51                  <1> 	push	ecx
  4744                              <1> 	;
  4745 00003429 89DE                <1> 	mov	esi, ebx
  4746 0000342B 89C7                <1> 	mov	edi, eax
  4747 0000342D 89C2                <1> 	mov	edx, eax
  4748 0000342F 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4749                              <1> cpt_0:
  4750 00003435 AD                  <1> 	lodsd
  4751 00003436 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4752                              <1> 	;jnz	short cpt_1 (*)
  4753                              <1> 	; 17/04/2021 (temporary (*)
  4754                              <1> 	;and	eax, eax (*)
  4755 00003438 741E                <1> 	jz	short cpt_2  ; 17/04/2021
  4756                              <1> 	
  4757                              <1> ; 17/04/2021
  4758                              <1> ; ('reload_page' procedure call is disabled as temporary)
  4759                              <1> ;
  4760                              <1> ;	; ebp = virtual (linear) address of the memory page
  4761                              <1> ;	call	reload_page ; 28/04/2015
  4762                              <1> ;	jc	short cpt_p_err
  4763                              <1> cpt_1:
  4764 0000343A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4765 0000343E 89C1                <1> 	mov	ecx, eax
  4766                              <1> 	; Allocate a new page for the child process
  4767 00003440 E82BFBFFFF          <1> 	call	allocate_page
  4768 00003445 721C                <1> 	jc	short cpt_p_err
  4769 00003447 57                  <1> 	push	edi
  4770 00003448 56                  <1> 	push	esi
  4771 00003449 89CE                <1> 	mov	esi, ecx
  4772 0000344B 89C7                <1> 	mov	edi, eax
  4773 0000344D B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4774 00003452 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4775 00003454 5E                  <1> 	pop	esi
  4776 00003455 5F                  <1> 	pop	edi
  4777                              <1> 	; 
  4778                              <1> ; 17/04/2021
  4779                              <1> ; ('add_to_swap_queue' procedure call is disabled as temporary)	
  4780                              <1> ;
  4781                              <1> ;	push	ebx
  4782                              <1> ;	push	eax
  4783                              <1> ;	mov	ebx, ebp
  4784                              <1> ;	; ebx = virtual address of the memory page
  4785                              <1> ;	call	add_to_swap_queue
  4786                              <1> ;	pop	eax
  4787                              <1> ;	pop	ebx
  4788                              <1> 	;
  4789                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4790 00003456 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4791                              <1> cpt_2:
  4792 00003458 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4793                              <1> 	;
  4794 00003459 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4795                              <1> 	;
  4796 0000345F 39D7                <1> 	cmp	edi, edx
  4797 00003461 72D2                <1> 	jb	short cpt_0
  4798                              <1> cpt_p_err:
  4799 00003463 59                  <1> 	pop	ecx
  4800 00003464 5A                  <1> 	pop	edx
  4801 00003465 5F                  <1> 	pop	edi
  4802 00003466 5E                  <1> 	pop	esi
  4803                              <1> 	;pop	ebx
  4804 00003467 58                  <1> 	pop	eax ; *
  4805                              <1> cpt_err:
  4806 00003468 C3                  <1> 	retn
  4807                              <1> 
  4808                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4809                              <1> 
  4810                              <1> ;; Data:
  4811                              <1> 
  4812                              <1> ; 09/03/2015
  4813                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4814                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4815                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes). 		  				
  4816                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4817                              <1> ;swpd_next:  dd 0 ; next free page block
  4818                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2018                                  %include 'sysdefs.s' ; 09/03/2015
  2019                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2020                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2021                              <1> ; ****************************************************************************
  2022                              <1> ; Retro UNIX 386 v1 Kernel - SYSDEFS.INC
  2023                              <1> ; Last Modification: 27/12/2021
  2024                              <1> ;
  2025                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2026                              <1> ; (Modified from 
  2027                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2028                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2029                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2030                              <1> ; ----------------------------------------------------------------------------
  2031                              <1> ;
  2032                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2033                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2034                              <1> ; <Bell Laboratories (17/3/1972)>
  2035                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2036                              <1> ;
  2037                              <1> ; ****************************************************************************
  2038                              <1> 
  2039                              <1> nproc 	equ	16  ; number of processes
  2040                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2041                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2042                              <1> 
  2043                              <1> ; 22/11/2021
  2044                              <1> NFILES	  equ	50
  2045                              <1> ; 27/12/2021
  2046                              <1> ;NFILES	  equ   32  ; temporary ! ( 27/12/2021)
  2047                              <1> OPENFILES equ	10  ; open files (for user) ; 28/03/2020
  2048                              <1> 
  2049                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2050                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2051                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2052                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2053                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2054                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2055                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2056                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2057                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2058                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2059                              <1> 	; '/core' dump file size = 32768 bytes
  2060                              <1>  
  2061                              <1> ; 08/03/2014 
  2062                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2063                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2064                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2065                              <1> 
  2066                              <1> ; 30/08/2013
  2067                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2068                              <1> 
  2069                              <1> ; 05/02/2014
  2070                              <1> ; process status
  2071                              <1> ;SFREE 	equ 0
  2072                              <1> ;SRUN	equ 1
  2073                              <1> ;SWAIT	equ 2
  2074                              <1> ;SZOMB	equ 3
  2075                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2076                              <1> 
  2077                              <1> ; 09/03/2015
  2078                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2079                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2080                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2081                              <1> 
  2082                              <1> ; 17/09/2015
  2083                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2084                              <1> 
  2085                              <1> ; 21/09/2015 (36) 
  2086                              <1> ; 01/07/2015 (35)
  2087                              <1> ; 14/07/2013 (0-34)
  2088                              <1> ; UNIX v1 system calls
  2089                              <1> _rele 	equ 0
  2090                              <1> _exit 	equ 1
  2091                              <1> _fork 	equ 2
  2092                              <1> _read 	equ 3
  2093                              <1> _write	equ 4
  2094                              <1> _open	equ 5
  2095                              <1> _close 	equ 6
  2096                              <1> _wait 	equ 7
  2097                              <1> _creat 	equ 8
  2098                              <1> _link 	equ 9
  2099                              <1> _unlink	equ 10
  2100                              <1> _exec	equ 11
  2101                              <1> _chdir	equ 12
  2102                              <1> _time 	equ 13
  2103                              <1> _mkdir 	equ 14
  2104                              <1> _chmod	equ 15
  2105                              <1> _chown	equ 16
  2106                              <1> _break	equ 17
  2107                              <1> _stat	equ 18
  2108                              <1> _seek	equ 19
  2109                              <1> _tell 	equ 20
  2110                              <1> _mount	equ 21
  2111                              <1> _umount	equ 22
  2112                              <1> _setuid	equ 23
  2113                              <1> _getuid	equ 24
  2114                              <1> _stime	equ 25
  2115                              <1> _quit	equ 26	
  2116                              <1> _intr	equ 27
  2117                              <1> _fstat	equ 28
  2118                              <1> _emt 	equ 29
  2119                              <1> _mdate 	equ 30
  2120                              <1> _stty 	equ 31
  2121                              <1> _gtty	equ 32
  2122                              <1> _ilgins	equ 33
  2123                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2124                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2125                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2126                              <1> 
  2127                              <1> %macro sys 1-4
  2128                              <1>     ; 13/04/2015
  2129                              <1>     ; Retro UNIX 386 v1 system call.		
  2130                              <1>     mov eax, %1
  2131                              <1>     %if %0 >= 2   
  2132                              <1>         mov ebx, %2
  2133                              <1>         %if %0 >= 3    
  2134                              <1>             mov ecx, %3
  2135                              <1>             %if %0 = 4
  2136                              <1>                mov edx, %4   
  2137                              <1>             %endif
  2138                              <1>         %endif
  2139                              <1>     %endif
  2140                              <1>     int 30h	   
  2141                              <1> %endmacro
  2142                              <1> 
  2143                              <1> ; 13/05/2015 - ERROR CODES
  2144                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2145                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2146                              <1> ; 14/05/2015
  2147                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2148                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2149                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2150                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2151                              <1> ; 16/05/2015		
  2152                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2153                              <1> ; 18/05/2015
  2154                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2155                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2156                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2157                              <1> ; 07/06/2015
  2158                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2159                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2160                              <1> ; 09/06/2015
  2161                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2162                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2163                              <1> ; 16/06/2015
  2164                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2165                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2166                              <1> ; 22/06/2015
  2167                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2168                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2169                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2170                              <1> ; 23/06/2015
  2171                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2172                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2173                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2174                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2175                              <1> ; 27/06/2015
  2176                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2177                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2178                              <1> ; 29/06/2015
  2179                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2180                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error	
  2181                              <1> 
  2182                              <1> ; 26/08/2015
  2183                              <1> ; 24/07/2015
  2184                              <1> ; 24/06/2015
  2185                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2186                              <1> ; 01/07/2015
  2187                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2188                              <1> ;
  2189                              <1> ; 22/11/2021
  2190                              <1> ERR_READ_ONLY_FS   equ 30  ; 'read only file system !' error
  2191                              <1> ; 28/11/2021
  2192                              <1> ERR_INV_FILE	   equ 255 ; 'invalid file (inode) !' error 	
  2193                              <1> 
  2194                              <1> ; 26/11/2021 ('no free blocks on disk !' error)
  2195                              <1> ERR_ALLOC	   equ 33  ; 'disk allocation error !'	
  2196                              <1> ; 04/12/2021
  2197                              <1> ERR_PERM_DENIED	   equ 11 ; 'permission denied !' error
  2198                              <1> ; 11/12/2021
  2199                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	   					 		
  2019                                  %include 'u0.s'      ; 15/03/2015
  2020                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2021                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2022                              <1> ; ****************************************************************************
  2023                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC
  2024                              <1> ; Last Modification: 26/12/2021
  2025                              <1> ; ----------------------------------------------------------------------------
  2026                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2027                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2028                              <1> ;
  2029                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2030                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2031                              <1> ; <Bell Laboratories (17/3/1972)>
  2032                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2033                              <1> ;
  2034                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2035                              <1> ;
  2036                              <1> ; ****************************************************************************
  2037                              <1> 
  2038                              <1> sys_init:
  2039                              <1> 	; 26/12/2021
  2040                              <1> 	; 27/11/2021
  2041                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 (test) compatibility modification
  2042                              <1> 	; 18/10/2015
  2043                              <1> 	; 28/08/2015
  2044                              <1> 	; 24/08/2015
  2045                              <1> 	; 14/08/2015
  2046                              <1> 	; 24/07/2015 
  2047                              <1> 	; 02/07/2015
  2048                              <1> 	; 01/07/2015
  2049                              <1> 	; 23/06/2015
  2050                              <1> 	; 15/04/2015
  2051                              <1> 	; 13/04/2015
  2052                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2053                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2054                              <1> 	;
  2055                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2056                              <1> 	;
  2057                              <1> 	;; 14/02/2014
  2058                              <1> 	;; 14/07/2013
  2059                              <1> 	;mov	ax, 41
  2060                              <1> 	;mov	[rootdir], ax
  2061                              <1> 	;mov	[u.cdir], ax
  2062                              <1> 	;and	al, 1 ; 15/04/2015
  2063                              <1> 	
  2064                              <1> 	; 27/11/2021
  2065                              <1> 	; 18/04/2021 - Retro UNIX 386 v2
  2066 00003469 31C0                <1> 	xor	eax, eax
  2067                              <1> 	; 12/12/2021 - Temporary
  2068 0000346B A2[706E0000]        <1> 	mov	[p.ttyc], al ; 0  ; test !!!
  2069 00003470 FEC0                <1> 	inc	al	; eax = 1 (root directory inode) ; runix v2 fs
  2070 00003472 A3[1C710000]        <1> 	mov	[rootdir], eax ; = 1 ; 28/10/2021 (32 bit)
  2071 00003477 A3[38710000]        <1> 	mov	[u.cdir], eax ; 28/10/2021 (32 bit)
  2072                              <1> 
  2073 0000347C A2[89710000]        <1> 	mov	[u.uno], al ; = 1
  2074 00003481 66A3[1A710000]      <1> 	mov	[mpid], ax ; 1 
  2075 00003487 66A3[106E0000]      <1> 	mov	[p.pid], ax ; 1
  2076 0000348D A2[A06E0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2077                              <1> 	;
  2078 00003492 B004                <1> 	mov	al, time_count ; 30/08/2013
  2079 00003494 A2[80710000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2080                              <1> 	; 02/07/2015
  2081 00003499 A1[38700000]        <1> 	mov	eax, [k_page_dir]
  2082 0000349E A3[98710000]        <1> 	mov	[u.pgdir], eax ; reset
  2083                              <1> 	; 18/10/2015
  2084                              <1> 	;sub	eax, eax
  2085                              <1> 	;mov	[u.ppgdir], eax ; 0
  2086                              <1>         ;
  2087 000034A3 E848030000          <1>  	call	epoch
  2088 000034A8 A3[28760000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2089                              <1> 	; 17/07/2013
  2090 000034AD E8A0060000          <1> 	call 	bf_init ; buffer initialization 
  2091                              <1> 	; 23/06/2015
  2092 000034B2 E8B9FAFFFF          <1> 	call	allocate_page
  2093                              <1> 	;;jc	error
  2094                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2095                              <1> 	; 05/12/2021
  2096 000034B7 7305                <1> 	jnc	short sysinit_1
  2097 000034B9 E990000000          <1> 	jmp	panic
  2098                              <1> sysinit_1:
  2099 000034BE A3[94710000]        <1> 	mov	[u.upage], eax ; user structure page	
  2100 000034C3 A3[B06E0000]        <1> 	mov	[p.upage], eax
  2101                              <1> 	;
  2102 000034C8 E814FBFFFF          <1> 	call	clear_page
  2103                              <1> 	;
  2104                              <1> 	; 14/08/2015
  2105 000034CD FA                  <1> 	cli
  2106                              <1> 	; 14/03/2015
  2107                              <1> 	; 17/01/2014
  2108 000034CE E8CE010000          <1> 	call	sp_init ; serial port initialization
  2109                              <1> 	; 14/08/2015
  2110 000034D3 FB                  <1> 	sti
  2111                              <1> 	;
  2112                              <1> 	; 30/06/2015
  2113                              <1> 	;mov	esi, kernel_init_ok_msg
  2114                              <1> 	;call 	print_msg
  2115                              <1> 	;
  2116 000034D4 30DB                <1> 	xor	bl, bl ; video page 0
  2117                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2118 000034D6 E887310000          <1> 	call 	vp_clr  ; 17/07/2013
  2119 000034DB FEC3                <1> 	inc	bl
  2120 000034DD 80FB08              <1> 	cmp	bl, 8
  2121 000034E0 72F4                <1> 	jb	short vp_clr_nxt
  2122                              <1> 	;
  2123                              <1> 	; 24/07/2015
  2124                              <1> 	;push	KDATA
  2125                              <1>         ;push	esp
  2126                              <1> 	;mov	[tss.esp0], esp
  2127                              <1>         ;mov	word [tss.ss0], KDATA
  2128                              <1> 	;
  2129                              <1> 	; 24/08/2015
  2130                              <1> 	;; temporary (01/07/2015)
  2131 000034E2 C605[80710000]04    <1> 	mov	byte [u.quant], time_count ; 4 
  2132                              <1> 			       ; it is not needed here !
  2133                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2134 000034E9 FE0D[29710000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2135                              <1> 			      ; 0 = executing a system call
  2136                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2137                              <1> 	;
  2138                              <1> 	;;; 06/08/2015
  2139                              <1> 	;;;call	getch ; wait for a key stroke
  2140                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2141                              <1> ;;sys_init_msg_wait:
  2142                              <1> ;;	push 	ecx
  2143                              <1> ;;	mov	al, 1
  2144                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2145                              <1> ;;	call	getc_n
  2146                              <1> ;;	pop	ecx
  2147                              <1> ;;	jnz	short sys_init_msg_ok
  2148                              <1> ;;	loop	sys_init_msg_wait
  2149                              <1> 	;
  2150                              <1> ;;sys_init_msg_ok:
  2151                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2152 000034EF 6A10                <1> 	push	KDATA ; ss
  2153 000034F1 54                  <1> 	push	esp
  2154 000034F2 9C                  <1> 	pushfd
  2155 000034F3 6A08                <1> 	push	KCODE ; cs
  2156 000034F5 68[22350000]        <1> 	push	init_exec ; eip
  2157 000034FA 8925[2C710000]      <1> 	mov	[u.sp], esp
  2158 00003500 1E                  <1> 	push	ds
  2159 00003501 06                  <1> 	push	es
  2160 00003502 0FA0                <1> 	push	fs
  2161 00003504 0FA8                <1> 	push	gs	
  2162 00003506 60                  <1> 	pushad
  2163 00003507 8925[30710000]      <1> 	mov	[u.usp], esp
  2164 0000350D E8151C0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2165                              <1> 		      ; and interrupt return components (for IRET)
  2166 00003512 61                  <1> 	popad
  2167 00003513 6658                <1> 	pop	ax ; gs
  2168 00003515 6658                <1> 	pop	ax ; fs
  2169 00003517 6658                <1> 	pop	ax ; es
  2170 00003519 6658                <1> 	pop	ax ; ds	
  2171 0000351B 58                  <1> 	pop	eax ; eip (init_exec)
  2172 0000351C 6658                <1> 	pop	ax ; cs (KCODE)
  2173 0000351E 58                  <1> 	pop	eax ; E-FLAGS
  2174 0000351F 58                  <1> 	pop	eax ; esp
  2175 00003520 6658                <1> 	pop	ax ; ss (KDATA)
  2176                              <1> 	;
  2177                              <1> 	; 26/12/2021 ([u.ppgdir] is zero already)
  2178                              <1> 	;xor	eax, eax ; 0
  2179                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2180                              <1> 	;
  2181                              <1> 	; 02/07/2015
  2182                              <1> 	; [u.pgdir ] = [k_page_dir]
  2183                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2184                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2185                              <1> init_exec:
  2186                              <1> 
  2187                              <1> ; temporary - 27/12/2021
  2188                              <1> ; clear faulty areas
  2189                              <1> ;mov ecx, (NFILES*fp.size)/4	
  2190                              <1> ;mov edi, fsp
  2191                              <1> ;xor eax, eax
  2192                              <1> ;rep stosd
  2193                              <1> ;mov edi, u.fp
  2194                              <1> ;mov cl, 10
  2195                              <1> ;rep stosb
  2196                              <1> 
  2197                              <1> 	; 13/03/2013
  2198                              <1> 	; 24/07/2013
  2199 00003522 BB[44350000]        <1> 	mov	ebx, init_file
  2200 00003527 B9[3C350000]        <1> 	mov	ecx, init_argp
  2201                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2202                              <1> 	; ECX contains address of argument list pointer
  2203                              <1> 	;
  2204                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2205                              <1> 			      ; 0 = executing a system call
  2206                              <1> 	sys	_exec  ; execute file
  2128                              <2> 
  2129                              <2> 
  2130 0000352C B80B000000          <2>  mov eax, %1
  2131                              <2>  %if %0 >= 2
  2132                              <2>  mov ebx, %2
  2133                              <2>  %if %0 >= 3
  2134                              <2>  mov ecx, %3
  2135                              <2>  %if %0 = 4
  2136                              <2>  mov edx, %4
  2137                              <2>  %endif
  2138                              <2>  %endif
  2139                              <2>  %endif
  2140 00003531 CD30                <2>  int 30h
  2207 00003533 7319                <1> 	jnc	short panic
  2208                              <1> 	;
  2209 00003535 BE[4C6D0000]        <1> 	mov	esi, etc_init_err_msg
  2210                              <1> 	; 22/11/2021
  2211                              <1> 	;call 	print_msg
  2212 0000353A EB17                <1> 	jmp	short key_to_reboot
  2213                              <1> 
  2214                              <1> ;align 4
  2215                              <1> init_argp:
  2216 0000353C [44350000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2217                              <1> init_file:
  2218                              <1> 	; 24/08/2015
  2219 00003544 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2219 0000354D 00                  <1>
  2220                              <1> panic:
  2221                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2222                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2223 0000354E BE[316D0000]        <1> 	mov 	esi, panic_msg
  2224                              <1> key_to_reboot: ; 22/11/2021
  2225 00003553 E819000000          <1> 	call 	print_msg
  2226                              <1> ;key_to_reboot:
  2227                              <1> 	; 15/11/2015
  2228 00003558 E8512F0000          <1> 	call 	getch 
  2229                              <1> 		; wait for a character from the current tty
  2230                              <1> 	;
  2231 0000355D B00A                <1> 	mov	al, 0Ah
  2232 0000355F 8A1D[66700000]      <1> 	mov	bl, [ptty] ; [active_page]
  2233 00003565 B407                <1> 	mov	ah, 07h ; Black background, 
  2234                              <1> 			; light gray forecolor
  2235 00003567 E853DFFFFF          <1> 	call 	write_tty
  2236 0000356C E9EEDBFFFF          <1> 	jmp	cpu_reset 
  2237                              <1> 
  2238                              <1> print_msg:
  2239                              <1> 	; 01/07/2015
  2240                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2241                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2242                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2243                              <1> 	;
  2244                              <1> 	;
  2245 00003571 AC                  <1> 	lodsb
  2246                              <1> pmsg1:
  2247 00003572 56                  <1> 	push 	esi
  2248 00003573 0FB61D[66700000]    <1> 	movzx	ebx, byte [ptty]
  2249 0000357A B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2250 0000357C E83EDFFFFF          <1> 	call 	write_tty
  2251 00003581 5E                  <1> 	pop	esi
  2252 00003582 AC                  <1> 	lodsb
  2253 00003583 20C0                <1> 	and 	al, al
  2254 00003585 75EB                <1> 	jnz 	short pmsg1
  2255 00003587 C3                  <1> 	retn
  2256                              <1> 	
  2257                              <1> ctrlbrk:
  2258                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2259                              <1> 	; 12/11/2015
  2260                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2261                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2262                              <1> 	;
  2263                              <1> 	; INT 1Bh (control+break) handler		
  2264                              <1> 	;
  2265                              <1>       	; Retro Unix 8086 v1 feature only!
  2266                              <1>       	;
  2267 00003588 66833D[84710000]00  <1> 	cmp 	word [u.intr], 0
  2268 00003590 7641                <1> 	jna 	short cbrk4
  2269                              <1> cbrk0:
  2270                              <1> 	; 12/11/2015
  2271                              <1> 	; 06/12/2013
  2272 00003592 66833D[86710000]00  <1> 	cmp 	word [u.quit], 0
  2273 0000359A 7437                <1> 	jz	short cbrk4
  2274                              <1> 	;
  2275                              <1> 	; 20/09/2013	
  2276                              <1> 	;push 	ax
  2277                              <1> 	; 04/12/2021
  2278 0000359C 50                  <1> 	push	eax
  2279 0000359D A0[66700000]        <1> 	mov	al, [ptty]
  2280                              <1> 	;
  2281                              <1> 	; 12/11/2015
  2282                              <1> 	;
  2283                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2284                              <1> 	; or ctrl+break from console (pseudo) tty
  2285                              <1> 	; (!redirection!)
  2286                              <1> 	;
  2287 000035A2 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2288 000035A4 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2289                              <1> 	;	
  2290                              <1> 	; Serial port interrupt handler sets [ptty]
  2291                              <1> 	; to the port's tty number (as temporary).
  2292                              <1> 	;
  2293                              <1> 	; If active process is using a stdin or 
  2294                              <1> 	; stdout redirection (by the shell),
  2295                              <1>         ; console tty keyboard must be available
  2296                              <1> 	; to terminate running process,
  2297                              <1> 	; in order to prevent a deadlock. 
  2298                              <1> 	;
  2299 000035A6 52                  <1> 	push	edx
  2300 000035A7 0FB615[89710000]    <1> 	movzx	edx, byte [u.uno]
  2301 000035AE 3A82[6F6E0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2302 000035B4 5A                  <1> 	pop	edx
  2303 000035B5 7412                <1> 	je	short cbrk2
  2304                              <1> cbrk1:
  2305 000035B7 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2306                              <1> 	; 06/12/2013
  2307 000035B9 3A05[6E710000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2308 000035BF 7408                <1> 	je	short cbrk2	
  2309 000035C1 3A05[6F710000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2310 000035C7 7509                <1> 	jne	short cbrk3	
  2311                              <1> cbrk2:
  2312                              <1> 	;; 06/12/2013
  2313                              <1> 	;mov	ax, [u.quit]
  2314                              <1> 	;and	ax, ax
  2315                              <1> 	;jz	short cbrk3
  2316                              <1> 	;
  2317                              <1> 	;xor	ax, ax ; 0
  2318                              <1> 	;dec	ax
  2319                              <1> 	; 04/12/2021
  2320 000035C9 31C0                <1> 	xor	eax, eax ; 0
  2321 000035CB 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2322                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2323 000035CC 66A3[86710000]      <1> 	mov	[u.quit], ax
  2324                              <1> cbrk3:
  2325                              <1> 	;pop	ax
  2326                              <1> 	; 04/12/2021
  2327 000035D2 58                  <1> 	pop	eax
  2328                              <1> cbrk4:
  2329 000035D3 C3                  <1> 	retn
  2330                              <1> 
  2331                              <1> com2_int:
  2332                              <1> 	; 07/11/2015 
  2333                              <1> 	; 24/10/2015
  2334                              <1> 	; 23/10/2015
  2335                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2336                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2337                              <1> 	; < serial port 2 interrupt handler >
  2338                              <1> 	;
  2339 000035D4 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2340                              <1> 	;push	eax
  2341 000035D7 66B80900            <1> 	mov	ax, 9
  2342 000035DB EB07                <1> 	jmp	short comm_int
  2343                              <1> com1_int:
  2344                              <1> 	; 07/11/2015
  2345                              <1> 	; 24/10/2015
  2346 000035DD 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2347                              <1> 	; 23/10/2015
  2348                              <1> 	;push	eax
  2349 000035E0 66B80800            <1> 	mov	ax, 8
  2350                              <1> comm_int:
  2351                              <1> 	; 20/11/2015
  2352                              <1> 	; 18/11/2015
  2353                              <1> 	; 17/11/2015
  2354                              <1> 	; 16/11/2015
  2355                              <1> 	; 09/11/2015
  2356                              <1> 	; 08/11/2015
  2357                              <1> 	; 07/11/2015
  2358                              <1> 	; 06/11/2015 (serial4.asm, 'serial')	
  2359                              <1> 	; 01/11/2015
  2360                              <1> 	; 26/10/2015
  2361                              <1> 	; 23/10/2015
  2362 000035E4 53                  <1> 	push	ebx
  2363 000035E5 56                  <1> 	push	esi
  2364 000035E6 57                  <1> 	push	edi
  2365 000035E7 1E                  <1> 	push 	ds
  2366 000035E8 06                  <1> 	push 	es
  2367                              <1> 	; 18/11/2015
  2368 000035E9 0F20DB              <1> 	mov	ebx, cr3
  2369 000035EC 53                  <1> 	push	ebx ; ****
  2370                              <1> 	;
  2371 000035ED 51                  <1> 	push	ecx ; ***
  2372 000035EE 52                  <1> 	push	edx ; **
  2373                              <1> 	;
  2374 000035EF BB10000000          <1> 	mov	ebx, KDATA
  2375 000035F4 8EDB                <1> 	mov	ds, bx
  2376 000035F6 8EC3                <1> 	mov	es, bx
  2377                              <1> 	;
  2378 000035F8 8B0D[38700000]      <1> 	mov	ecx, [k_page_dir]
  2379 000035FE 0F22D9              <1> 	mov	cr3, ecx
  2380                              <1> 	; 20/11/2015
  2381                              <1> 	; Interrupt identification register
  2382 00003601 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2383                              <1> 	;
  2384 00003605 3C08                <1> 	cmp 	al, 8 
  2385 00003607 7702                <1> 	ja 	short com_i0
  2386                              <1> 	;
  2387                              <1> 	; 20/11/2015
  2388                              <1> 	; 17/11/2015
  2389                              <1> 	; 16/11/2015
  2390                              <1> 	; 15/11/2015
  2391                              <1> 	; 24/10/2015
  2392                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2393                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2394                              <1> 	; < serial port 1 interrupt handler >
  2395                              <1> 	;
  2396 00003609 FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2397                              <1> com_i0:
  2398                              <1> 	;push	eax ; *
  2399                              <1> 	; 07/11/2015
  2400 0000360B A2[A6700000]        <1> 	mov 	byte [ccomport], al
  2401                              <1> 	; 09/11/2015
  2402 00003610 0FB7D8              <1> 	movzx	ebx, ax ; 8 or 9
  2403                              <1> 	; 17/11/2015
  2404                              <1>  	; reset request for response status
  2405 00003613 88A3[9C700000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2406                              <1> 	;
  2407                              <1> 	; 20/11/2015
  2408 00003619 EC                  <1> 	in	al, dx		; read interrupt id. register
  2409 0000361A EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2410 0000361C 2404                <1> 	and	al, 4		; received data available?	
  2411 0000361E 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2412                              <1> 	;
  2413                              <1> 	; 20/11/2015
  2414 00003620 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2415 00003623 EC                  <1> 	in	al, dx     	; read character
  2416                              <1> 	;JMP	$+2	   	; I/O DELAY
  2417                              <1> 	; 08/11/2015
  2418                              <1> 	; 07/11/2015
  2419 00003624 89DE                <1> 	mov	esi, ebx 
  2420 00003626 89DF                <1> 	mov	edi, ebx
  2421 00003628 81C6[A0700000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2422 0000362E 81C7[A2700000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2423 00003634 8806                <1> 	mov	[esi], al ; received char (current char)
  2424                              <1> 	; query
  2425 00003636 20C0                <1> 	and	al, al
  2426 00003638 7527                <1> 	jnz	short com_i2
  2427                              <1>    	; response
  2428                              <1> 	; 17/11/2015
  2429                              <1> 	; set request for response status
  2430 0000363A FE83[9C700000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2431                              <1> 	;
  2432 00003640 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2433 00003644 EC                  <1> 	in	al, dx	   	; read line status register 
  2434 00003645 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2435 00003647 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2436 00003649 7445                <1> 	jz	short com_eoi 	; no
  2437 0000364B B0FF                <1> 	mov 	al, 0FFh   	; response			
  2438 0000364D 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2439 00003651 EE                  <1> 	out	dx, al	   	; send on serial port
  2440                              <1> 	; 17/11/2015
  2441 00003652 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2442 00003655 7502                <1> 	jne 	short com_i1    ; no
  2443 00003657 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2444                              <1> com_i1:
  2445                              <1> 	; 17/11/2015
  2446                              <1> 	; reset request for response status (again)
  2447 00003659 FE8B[9C700000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2448 0000365F EB2F                <1> 	jmp	short com_eoi
  2449                              <1> com_i2:	
  2450                              <1> 	; 08/11/2015
  2451 00003661 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2452 00003663 7417                <1> 	je	short com_i3	; (check for response signal)
  2453                              <1> 	; 07/11/2015
  2454 00003665 3C04                <1> 	cmp	al, 04h	; EOT
  2455 00003667 751C                <1> 	jne	short com_i4	
  2456                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2457                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2458                              <1> 	; 08/11/2015
  2459                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2460 00003669 861D[66700000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2461 0000366F E814FFFFFF          <1> 	call 	ctrlbrk
  2462 00003674 861D[66700000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2463                              <1> 	;mov	al, 04h ; EOT
  2464                              <1> 	; 08/11/2015
  2465 0000367A EB09                <1> 	jmp	short com_i4	
  2466                              <1> com_i3:
  2467                              <1> 	; 08/11/2015
  2468                              <1> 	; If 0FFh has been received just after a query
  2469                              <1> 	; (schar, ZERO), it is a response signal.
  2470                              <1> 	; 17/11/2015
  2471 0000367C 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2472 0000367F 7704                <1> 	ja	short com_i4 ; no
  2473                              <1> 	; reset query status (schar)
  2474 00003681 8807                <1> 	mov	[edi], al ; 0FFh
  2475 00003683 FEC0                <1> 	inc	al ; 0
  2476                              <1> com_i4:
  2477                              <1> 	; 27/07/2014
  2478                              <1> 	; 09/07/2014
  2479 00003685 D0E3                <1> 	shl	bl, 1	
  2480 00003687 81C3[68700000]      <1> 	add	ebx, ttychr
  2481                              <1> 	; 23/07/2014 (always overwrite)
  2482                              <1> 	;;cmp	word [ebx], 0
  2483                              <1> 	;;ja	short com_eoi
  2484                              <1> 	;
  2485 0000368D 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2486                              <1> 			    ; scan code = 0
  2487                              <1> com_eoi:
  2488                              <1> 	;mov	al, 20h
  2489                              <1> 	;out	20h, al	   ; end of interrupt
  2490                              <1> 	;
  2491                              <1> 	; 07/11/2015
  2492                              <1>       	;pop	eax ; *
  2493 00003690 A0[A6700000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2494                              <1> 	; al = tty number (8 or 9)
  2495 00003695 E8671B0000          <1>         call	wakeup
  2496                              <1> com_iret:
  2497                              <1> 	; 23/10/2015
  2498 0000369A 5A                  <1> 	pop	edx ; **
  2499 0000369B 59                  <1> 	pop	ecx ; ***
  2500                              <1> 	; 18/11/2015
  2501                              <1> 	;pop	eax ; ****
  2502                              <1> 	;mov	cr3, eax
  2503                              <1> 	;jmp	iiret
  2504 0000369C E901D4FFFF          <1> 	jmp	iiretp
  2505                              <1> 
  2506                              <1> ;iiretp: ; 01/09/2015
  2507                              <1> ;	; 28/08/2015
  2508                              <1> ;	pop	eax ; (*) page directory
  2509                              <1> ;	mov	cr3, eax
  2510                              <1> ;iiret:
  2511                              <1> ;	; 22/08/2014
  2512                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2513                              <1> ;	out	20h, al	; 8259 PORT
  2514                              <1> ;	;
  2515                              <1> ;	pop	es
  2516                              <1> ;	pop	ds
  2517                              <1> ;	pop	edi
  2518                              <1> ;	pop	esi
  2519                              <1> ;	pop	ebx ; 29/08/2014
  2520                              <1> ;	pop 	eax
  2521                              <1> ;	iretd
  2522                              <1> 
  2523                              <1> sp_init:
  2524                              <1> 	; 07/11/2015
  2525                              <1> 	; 29/10/2015
  2526                              <1> 	; 26/10/2015
  2527                              <1> 	; 23/10/2015
  2528                              <1> 	; 29/06/2015
  2529                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2530                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2531                              <1> 	; Initialization of Serial Port Communication Parameters
  2532                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2533                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2534                              <1> 	;
  2535                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2536                              <1> 	;
  2537                              <1> 	; INPUT:  (29/06/2015)
  2538                              <1> 	;	AL = 0 for COM1
  2539                              <1> 	;	     1 for COM2
  2540                              <1> 	;	AH = Communication parameters	
  2541                              <1> 	;
  2542                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2543                              <1> 	;	Bit	4	3	2	1	0
  2544                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2545                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2546                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2547                              <1> 	;		11 = even
  2548                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2549                              <1> 	;		Retro UNIX 386 v1 feature only !
  2550                              <1> 	;	Bit	7    6    5  | Baud rate
  2551                              <1> 	;		------------------------
  2552                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2553                              <1> 	;		0    0    1  | 9600 (12)
  2554                              <1> 	;		0    1    0  | 19200 (6) 
  2555                              <1> 	;		0    1	  1  | 38400 (3) 
  2556                              <1> 	;		1    0	  0  | 14400 (8)
  2557                              <1> 	;		1    0	  1  | 28800 (4)
  2558                              <1> 	;		1    1    0  | 57600 (2)
  2559                              <1> 	;		1    1    1  | 115200 (1) 	
  2560                              <1> 	
  2561                              <1> 	; References:	
  2562                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2563                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2564                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2565                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2566                              <1> 	;
  2567                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2568                              <1> 	;
  2569 000036A1 BB[A2700000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2570 000036A6 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2571                              <1> 	 ; 29/10/2015
  2572 000036AA 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2573 000036AE E86F000000          <1> 	call	sp_i3	; call A4	
  2574 000036B3 A880                <1> 	test	al, 80h
  2575 000036B5 7410                <1> 	jz	short sp_i0 ; OK..
  2576                              <1> 		; Error !
  2577                              <1> 	;mov	dx, 3F8h
  2578 000036B7 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2579 000036BA 66B90E03            <1> 	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2580 000036BE E85F000000          <1> 	call	sp_i3	; call A4	
  2581 000036C3 A880                <1> 	test	al, 80h
  2582 000036C5 7508                <1> 	jnz	short sp_i1
  2583                              <1> sp_i0:
  2584                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2585                              <1>         ; (INT 14h initialization code disables interrupts.)
  2586                              <1> 	;
  2587 000036C7 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2588 000036CA E8DD000000          <1> 	call	sp_i5 ; 29/06/2015
  2589                              <1> sp_i1:
  2590 000036CF 43                  <1> 	inc	ebx
  2591 000036D0 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2592                              <1> 	 ; 29/10/2015
  2593 000036D4 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2594 000036D8 E845000000          <1> 	call	sp_i3	; call A4	
  2595 000036DD A880                <1> 	test	al, 80h
  2596 000036DF 7410                <1> 	jz	short sp_i2 ; OK..
  2597                              <1> 		; Error !
  2598                              <1> 	;mov	dx, 2F8h
  2599 000036E1 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2600 000036E4 66B90E03            <1> 	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2601 000036E8 E835000000          <1> 	call	sp_i3	; call A4	
  2602 000036ED A880                <1> 	test	al, 80h
  2603 000036EF 7530                <1> 	jnz	short sp_i7
  2604                              <1> sp_i2:
  2605 000036F1 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2606                              <1> sp_i6:
  2607                              <1> 	;; COM2 - enabling IRQ 3
  2608                              <1> 	; 07/11/2015
  2609                              <1> 	; 26/10/2015
  2610 000036F4 9C                  <1> 	pushf
  2611 000036F5 FA                  <1> 	cli
  2612                              <1> 	;
  2613 000036F6 66BAFC02            <1> 	mov	dx, 2FCh   		; modem control register
  2614 000036FA EC                  <1> 	in	al, dx 	   		; read register
  2615 000036FB EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2616 000036FD 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2617 000036FF EE                  <1> 	out	dx, al     		; write back to register
  2618 00003700 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2619 00003702 66BAF902            <1> 	mov	dx, 2F9h   		; interrupt enable register
  2620 00003706 EC                  <1> 	in	al, dx     		; read register
  2621 00003707 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2622                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2623 00003709 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2624 0000370B EE                  <1> 	out	dx, al 	   		; write back to register
  2625 0000370C EB00                <1> 	JMP	$+2        		; I/O DELAY
  2626 0000370E E421                <1> 	in	al, 21h    		; read interrupt mask register
  2627 00003710 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2628 00003712 24F7                <1> 	and	al, 0F7h   		; enable IRQ 3 (COM2)
  2629 00003714 E621                <1> 	out	21h, al    		; write back to register
  2630                              <1> 	;
  2631                              <1> 	; 23/10/2015
  2632 00003716 B8[D4350000]        <1> 	mov 	eax, com2_int
  2633 0000371B A3[CA3B0000]        <1> 	mov	[com2_irq3], eax
  2634                              <1> 	; 26/10/2015
  2635 00003720 9D                  <1> 	popf	
  2636                              <1> sp_i7:
  2637 00003721 C3                  <1> 	retn
  2638                              <1> 
  2639                              <1> sp_i3:
  2640                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2641                              <1> 	; 28/10/2015
  2642 00003722 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2643 00003724 B000                <1> 	mov	al, 0
  2644 00003726 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2645 00003727 EB00                <1> 	JMP	$+2			; I/O DELAY
  2646 00003729 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2647 0000372C B080                <1> 	mov	al, 80h			
  2648 0000372E EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2649                              <1> 	;-----	SET BAUD RATE DIVISOR
  2650                              <1> 	; 26/10/2015
  2651 0000372F 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2652                              <1> 					; of the divisor value
  2653 00003732 88C8                <1> 	mov	al, cl	; 1
  2654 00003734 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2655                              <1> 					; 2 = 57600 baud
  2656                              <1> 					; 3 = 38400 baud
  2657                              <1> 					; 6 = 19200 baud
  2658                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2659 00003735 EB00                <1> 	JMP	$+2			; I/O DELAY
  2660 00003737 28C0                <1> 	sub	al, al
  2661 00003739 FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2662                              <1> 					; of the divisor value
  2663 0000373B EE                  <1> 	out	dx, al ; 0
  2664 0000373C EB00                <1> 	JMP	$+2			; I/O DELAY
  2665                              <1> 	;	
  2666 0000373E 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2667                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2668 00003740 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2669 00003743 EE                  <1> 	out	dx, al			
  2670 00003744 EB00                <1> 	JMP	$+2			; I/O DELAY
  2671                              <1> 	; 29/10/2015
  2672 00003746 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2673 00003748 30C0                <1> 	xor	al, al			; 0
  2674 0000374A EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2675 0000374B EB00                <1> 	JMP	$+2	
  2676                              <1> sp_i4:
  2677                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2678                              <1> 	; 29/06/2015 (line status after modem status)
  2679 0000374D 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2680                              <1> sp_i4s:
  2681 00003750 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2682 00003751 EB00                <1> 	JMP	$+2			; I/O DELAY
  2683 00003753 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2684 00003755 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2685                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2686 00003757 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2687                              <1> 	; AL = Line status, AH = Modem status
  2688 00003758 C3                  <1> 	retn
  2689                              <1> 
  2690                              <1> sp_status:
  2691                              <1> 	; 29/06/2015
  2692                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2693                              <1> 	; Get serial port status
  2694 00003759 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2695 0000375D 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2696                              <1> 					; dx = 2FEh for COM2
  2697 0000375F EBEF                <1> 	jmp	short sp_i4s
  2698                              <1> 
  2699                              <1> sp_setp: ; Set serial port communication parameters
  2700                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2701                              <1> 	; 07/11/2015
  2702                              <1> 	; 29/10/2015
  2703                              <1> 	; 29/06/2015
  2704                              <1> 	; Retro UNIX 386 v1 feature only !	
  2705                              <1> 	;
  2706                              <1> 	; INPUT:
  2707                              <1> 	;	AL = 0 for COM1
  2708                              <1> 	;	     1 for COM2
  2709                              <1> 	;	AH = Communication parameters (*)
  2710                              <1> 	; OUTPUT:
  2711                              <1> 	;	CL = Line status
  2712                              <1> 	;	CH = Modem status
  2713                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2714                              <1> 	;		 'invalid parameter !' 
  2715                              <1> 	;		 	 or
  2716                              <1> 	;		 'device not ready !' error
  2717                              <1> 	;	
  2718                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2719                              <1> 	;	Bit	4	3	2	1	0
  2720                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2721                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2722                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2723                              <1> 	;		11 = even
  2724                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2725                              <1> 	;		Retro UNIX 386 v1 feature only !
  2726                              <1> 	;	Bit	7    6    5  | Baud rate
  2727                              <1> 	;		------------------------
  2728                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2729                              <1> 	;		0    0    1  | 9600 (12)
  2730                              <1> 	;		0    1    0  | 19200 (6) 
  2731                              <1> 	;		0    1	  1  | 38400 (3) 
  2732                              <1> 	;		1    0	  0  | 14400 (8)
  2733                              <1> 	;		1    0	  1  | 28800 (4)
  2734                              <1> 	;		1    1    0  | 57600 (2)
  2735                              <1> 	;		1    1    1  | 115200 (1) 
  2736                              <1> 	;
  2737                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2738                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2739                              <1> 	;
  2740                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2741                              <1> 	;
  2742 00003761 66BAF803            <1> 	mov	dx, 3F8h
  2743 00003765 BB[A2700000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2744 0000376A 3C01                <1> 	cmp	al, 1
  2745 0000376C 776C                <1> 	ja 	short sp_invp_err
  2746 0000376E 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2747 00003770 FECE                <1> 	dec	dh ; 2F8h
  2748 00003772 43                  <1> 	inc	ebx ; COM2 control byte offset
  2749                              <1> sp_setp1:
  2750                              <1> 	; 29/10/2015
  2751 00003773 8823                <1> 	mov	[ebx], ah
  2752 00003775 0FB6CC              <1> 	movzx 	ecx, ah
  2753 00003778 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2754 0000377B 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2755 0000377E 8A81[E9370000]      <1> 	mov	al, [ecx+b_div_tbl]
  2756 00003784 6689C1              <1> 	mov	cx, ax
  2757 00003787 E896FFFFFF          <1> 	call	sp_i3
  2758 0000378C 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2759 0000378F A880                <1> 	test	al, 80h
  2760 00003791 740F                <1> 	jz	short sp_setp2
  2761 00003793 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2762                              <1> stp_dnr_err:
  2763 00003796 C705[AC710000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2763 0000379E 0000                <1>
  2764                              <1> 	; CL = Line status, CH = Modem status
  2765 000037A0 F9                  <1> 	stc
  2766 000037A1 C3                  <1> 	retn
  2767                              <1> sp_setp2:
  2768 000037A2 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2769                              <1>         ;jna	sp_i6
  2770                              <1> 		      ; COM1 (3F?h)
  2771                              <1> 	; 24/12/2021
  2772 000037A5 7705                <1> 	ja	short sp_i5
  2773 000037A7 E948FFFFFF          <1> 	jmp	sp_i6
  2774                              <1> sp_i5: 
  2775                              <1> 	; 07/11/2015
  2776                              <1> 	; 26/10/2015
  2777                              <1> 	; 29/06/2015
  2778                              <1> 	;
  2779                              <1> 	;; COM1 - enabling IRQ 4
  2780 000037AC 9C                  <1> 	pushf
  2781 000037AD FA                  <1> 	cli
  2782 000037AE 66BAFC03            <1> 	mov	dx, 3FCh   		; modem control register
  2783 000037B2 EC                  <1> 	in	al, dx 	   		; read register
  2784 000037B3 EB00                <1> 	JMP	$+2			; I/O DELAY
  2785 000037B5 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2786 000037B7 EE                  <1> 	out	dx, al     		; write back to register
  2787 000037B8 EB00                <1> 	JMP	$+2			; I/O DELAY
  2788 000037BA 66BAF903            <1> 	mov	dx, 3F9h   		; interrupt enable register
  2789 000037BE EC                  <1> 	in	al, dx     		; read register
  2790 000037BF EB00                <1> 	JMP	$+2			; I/O DELAY
  2791                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2792 000037C1 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2793 000037C3 EE                  <1> 	out	dx, al 	   		; write back to register
  2794 000037C4 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2795 000037C6 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2796 000037C8 EB00                <1> 	JMP	$+2			; I/O DELAY
  2797 000037CA 24EF                <1> 	and	al, 0EFh   		; enable IRQ 4 (COM1)
  2798 000037CC E621                <1> 	out	21h, al    		; write back to register
  2799                              <1> 	;
  2800                              <1> 	; 23/10/2015
  2801 000037CE B8[DD350000]        <1> 	mov 	eax, com1_int
  2802 000037D3 A3[C63B0000]        <1> 	mov	[com1_irq4], eax
  2803                              <1> 	; 26/10/2015
  2804 000037D8 9D                  <1> 	popf
  2805 000037D9 C3                  <1> 	retn
  2806                              <1> 
  2807                              <1> sp_invp_err:
  2808 000037DA C705[AC710000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2808 000037E2 0000                <1>
  2809 000037E4 31C9                <1> 	xor	ecx, ecx
  2810 000037E6 49                  <1> 	dec	ecx ; 0FFFFh
  2811 000037E7 F9                  <1> 	stc
  2812 000037E8 C3                  <1> 	retn
  2813                              <1> 
  2814                              <1> ; 29/10/2015
  2815                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2816 000037E9 010C0603080401      <1> 	db 1, 12, 6, 3, 8, 4, 1
  2817                              <1> 
  2818                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2819                              <1> epoch:
  2820                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2821                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2822                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2823                              <1> 	; 'epoch' procedure prototype: 
  2824                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2825                              <1> 	; 14/11/2012
  2826                              <1> 	; unixboot.asm (boot file configuration)
  2827                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2828                              <1> 	; 21/7/2012
  2829                              <1> 	; 15/7/2012
  2830                              <1> 	; 14/7/2012		
  2831                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2832                              <1> 	; compute current date and time as UNIX Epoch/Time
  2833                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2834                              <1> 	;
  2835                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2836                              <1> 	;
  2837 000037F0 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2838 000037F5 86E9                <1>         xchg 	ch,cl
  2839 000037F7 66890D[A66D0000]    <1>         mov 	[hour], cx
  2840 000037FE 86F2                <1>         xchg 	dh,dl
  2841 00003800 668915[AA6D0000]    <1>         mov 	[second], dx
  2842                              <1> 	;
  2843 00003807 E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2844 0000380C 86E9                <1>         xchg 	ch,cl
  2845 0000380E 66890D[A06D0000]    <1>         mov 	[year], cx
  2846 00003815 86F2                <1>         xchg 	dh,dl
  2847 00003817 668915[A26D0000]    <1>         mov 	[month], dx
  2848                              <1> 	;
  2849 0000381E 66B93030            <1> 	mov 	cx, 3030h
  2850                              <1> 	;
  2851 00003822 A0[A66D0000]        <1> 	mov 	al, [hour] ; Hour
  2852                              <1>         	; AL <= BCD number)
  2853 00003827 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2854                              <1> 					; AH = AL / 10h
  2855                              <1> 					; AL = AL MOD 10h
  2856 00003829 D50A                <1>         aad 	; AX= AH*10+AL
  2857 0000382B A2[A66D0000]        <1> 	mov 	[hour], al
  2858 00003830 A0[A76D0000]        <1> 	mov 	al, [hour+1] ; Minute
  2859                              <1>         	; AL <= BCD number)
  2860 00003835 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2861                              <1> 					; AH = AL / 10h
  2862                              <1> 					; AL = AL MOD 10h
  2863 00003837 D50A                <1>         aad 	; AX= AH*10+AL
  2864 00003839 A2[A86D0000]        <1> 	mov 	[minute], al
  2865 0000383E A0[AA6D0000]        <1> 	mov 	al, [second] ; Second
  2866                              <1>         	; AL <= BCD number)
  2867 00003843 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2868                              <1> 					; AH = AL / 10h
  2869                              <1> 					; AL = AL MOD 10h
  2870 00003845 D50A                <1>         aad 	; AX= AH*10+AL
  2871 00003847 A2[AA6D0000]        <1> 	mov 	[second], al
  2872 0000384C 66A1[A06D0000]      <1> 	mov 	ax, [year] ; Year (century)
  2873                              <1> 	;push 	ax
  2874                              <1> 	; 04/12/2021
  2875 00003852 50                  <1> 	push	eax
  2876                              <1> 	   	; AL <= BCD number)
  2877 00003853 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2878                              <1> 					; AH = AL / 10h
  2879                              <1> 					; AL = AL MOD 10h
  2880 00003855 D50A                <1>         aad 	; AX= AH*10+AL
  2881 00003857 B464                <1> 	mov 	ah, 100
  2882 00003859 F6E4                <1> 	mul 	ah
  2883 0000385B 66A3[A06D0000]      <1> 	mov 	[year], ax
  2884                              <1> 	;pop	ax
  2885                              <1> 	; 04/12/2021
  2886 00003861 58                  <1> 	pop	eax
  2887 00003862 88E0                <1> 	mov	al, ah
  2888                              <1>         	; AL <= BCD number)
  2889 00003864 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2890                              <1> 					; AH = AL / 10h
  2891                              <1> 					; AL = AL MOD 10h
  2892 00003866 D50A                <1>         aad 	; AX= AH*10+AL
  2893 00003868 660105[A06D0000]    <1> 	add 	[year], ax
  2894 0000386F A0[A26D0000]        <1> 	mov 	al, [month] ; Month
  2895                              <1>            	; AL <= BCD number)
  2896 00003874 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2897                              <1> 					; AH = AL / 10h
  2898                              <1> 					; AL = AL MOD 10h
  2899 00003876 D50A                <1>         aad 	; AX= AH*10+AL
  2900 00003878 A2[A26D0000]        <1> 	mov 	[month], al	
  2901 0000387D A0[A36D0000]        <1>         mov     al, [month+1]      	; Day
  2902                              <1>            	; AL <= BCD number)
  2903 00003882 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2904                              <1> 					; AH = AL / 10h
  2905                              <1> 					; AL = AL MOD 10h
  2906 00003884 D50A                <1>         aad 	; AX= AH*10+AL
  2907 00003886 A2[A46D0000]        <1>         mov     [day], al
  2908                              <1> 	
  2909                              <1> convert_to_epoch:
  2910                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  2911                              <1> 	; 09/04/2013 (retro UNIX 8086 v1)
  2912                              <1> 	;
  2913                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  2914                              <1> 	;
  2915                              <1> 	; Derived from DALLAS Semiconductor
  2916                              <1> 	; Application Note 31 (DS1602/DS1603)
  2917                              <1> 	; 6 May 1998
  2918 0000388B 29C0                <1> 	sub 	eax, eax
  2919 0000388D 66A1[A06D0000]      <1> 	mov 	ax, [year]
  2920 00003893 662DB207            <1> 	sub 	ax, 1970
  2921 00003897 BA6D010000          <1> 	mov 	edx, 365
  2922 0000389C F7E2                <1> 	mul 	edx
  2923 0000389E 31DB                <1> 	xor 	ebx, ebx
  2924 000038A0 8A1D[A26D0000]      <1> 	mov 	bl, [month]
  2925 000038A6 FECB                <1> 	dec 	bl
  2926 000038A8 D0E3                <1> 	shl 	bl, 1
  2927                              <1> 	;sub	edx, edx
  2928 000038AA 668B93[AC6D0000]    <1> 	mov 	dx, [EBX+DMonth]
  2929 000038B1 8A1D[A46D0000]      <1>         mov     bl, [day]
  2930 000038B7 FECB                <1> 	dec 	bl
  2931 000038B9 01D0                <1> 	add 	eax, edx
  2932 000038BB 01D8                <1> 	add 	eax, ebx
  2933                              <1> 			; EAX = days since 1/1/1970
  2934 000038BD 668B15[A06D0000]    <1> 	mov 	dx, [year]
  2935 000038C4 6681EAB107          <1> 	sub 	dx, 1969
  2936 000038C9 66D1EA              <1> 	shr 	dx, 1
  2937 000038CC 66D1EA              <1> 	shr 	dx, 1		
  2938                              <1> 		; (year-1969)/4
  2939 000038CF 01D0                <1> 	add 	eax, edx
  2940                              <1> 			; + leap days since 1/1/1970
  2941 000038D1 803D[A26D0000]02    <1> 	cmp 	byte [month], 2	; if past february
  2942 000038D8 7610                <1> 	jna 	short cte1
  2943 000038DA 668B15[A06D0000]    <1> 	mov 	dx, [year]
  2944 000038E1 6683E203            <1> 	and 	dx, 3 ; year mod 4
  2945 000038E5 7503                <1> 	jnz 	short cte1		
  2946                              <1> 			; and if leap year
  2947 000038E7 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  2948                              <1> cte1: 			; compute seconds since 1/1/1970
  2949 000038EA BA18000000          <1> 	mov 	edx, 24
  2950 000038EF F7E2                <1> 	mul	edx
  2951 000038F1 8A15[A66D0000]      <1> 	mov 	dl, [hour]
  2952 000038F7 01D0                <1> 	add 	eax, edx
  2953                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  2954                              <1> 	;mov	ebx, 60
  2955 000038F9 B33C                <1> 	mov	bl, 60
  2956 000038FB F7E3                <1> 	mul	ebx
  2957 000038FD 8A15[A86D0000]      <1> 	mov 	dl, [minute]
  2958 00003903 01D0                <1> 	add 	eax, edx
  2959                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  2960                              <1> 	;mov 	ebx, 60
  2961 00003905 F7E3                <1> 	mul	ebx
  2962 00003907 8A15[AA6D0000]      <1> 	mov 	dl, [second]
  2963 0000390D 01D0                <1> 	add 	eax, edx
  2964                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  2965 0000390F C3                  <1> 	retn
  2966                              <1> 
  2967                              <1> get_rtc_time:
  2968                              <1> 	; 15/03/2015
  2969                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  2970                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  2971                              <1> 	; INT 1Ah
  2972                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  2973                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  2974                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  2975                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  2976                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  2977                              <1> 	;								
  2978                              <1> RTC_20: 				; GET RTC TIME
  2979 00003910 FA                  <1> 	cli
  2980 00003911 E821D3FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  2981 00003916 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  2982                              <1> 
  2983 00003918 B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  2984 0000391A E802D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  2985 0000391F 88C6                <1> 	MOV	DH, AL			; SAVE
  2986 00003921 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  2987 00003923 E8F9D2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  2988 00003928 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  2989 0000392A 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  2990 0000392C B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  2991 0000392E E8EED2FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  2992 00003933 88C1                <1> 	MOV	CL, AL			; SAVE
  2993 00003935 B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  2994 00003937 E8E5D2FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  2995 0000393C 88C5                <1> 	MOV	CH, AL			; SAVE
  2996 0000393E F8                  <1> 	CLC				; SET CY= 0
  2997                              <1> RTC_29:
  2998 0000393F FB                  <1> 	sti
  2999 00003940 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3000                              <1> 
  3001                              <1> get_rtc_date:
  3002                              <1> 	; 15/03/2015
  3003                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3004                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3005                              <1> 	; INT 1Ah
  3006                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3007                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3008                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3009                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3010                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3011                              <1> 	;
  3012                              <1> RTC_40: 				; GET RTC DATE
  3013 00003941 FA                  <1> 	cli
  3014 00003942 E8F0D2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3015 00003947 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3016                              <1> 
  3017 00003949 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3018 0000394B E8D1D2FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3019 00003950 88C2                <1> 	MOV	DL, AL			; SAVE
  3020 00003952 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3021 00003954 E8C8D2FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3022 00003959 88C6                <1> 	MOV	DH, AL			; SAVE
  3023 0000395B B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3024 0000395D E8BFD2FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3025 00003962 88C1                <1> 	MOV	CL, AL			; SAVE
  3026 00003964 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3027 00003966 E8B6D2FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3028 0000396B 88C5                <1> 	MOV	CH, AL			; SAVE
  3029 0000396D F8                  <1> 	CLC				; SET CY=0
  3030                              <1> RTC_49:
  3031 0000396E FB                  <1> 	sti
  3032 0000396F C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3033                              <1> 
  3034                              <1> set_date_time:
  3035                              <1> convert_from_epoch:
  3036                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3037                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3038                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3039                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3040                              <1> 	;
  3041                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3042                              <1> 	;
  3043                              <1> 	; Derived from DALLAS Semiconductor
  3044                              <1> 	; Application Note 31 (DS1602/DS1603)
  3045                              <1> 	; 6 May 1998
  3046                              <1> 	;
  3047                              <1> 	; INPUT:
  3048                              <1> 	; EAX = Unix (Epoch) Time
  3049                              <1> 	;
  3050 00003970 31D2                <1> 	xor 	edx, edx
  3051 00003972 B93C000000          <1> 	mov 	ecx, 60
  3052 00003977 F7F1                <1> 	div	ecx
  3053                              <1> 	;mov 	[imin], eax   ; whole minutes
  3054                              <1> 			  ; since 1/1/1970
  3055 00003979 668915[AA6D0000]    <1> 	mov 	[second], dx  ; leftover seconds
  3056 00003980 29D2                <1> 	sub 	edx, edx
  3057 00003982 F7F1                <1> 	div	ecx
  3058                              <1> 	;mov 	[ihrs], eax   ; whole hours
  3059                              <1> 	;		      ; since 1/1/1970
  3060 00003984 668915[A86D0000]    <1> 	mov 	[minute], dx  ; leftover minutes
  3061 0000398B 31D2                <1> 	xor	edx, edx
  3062                              <1> 	;mov 	cx, 24
  3063 0000398D B118                <1> 	mov 	cl, 24
  3064 0000398F F7F1                <1> 	div	ecx
  3065                              <1> 	;mov 	[iday], ax   ; whole days
  3066                              <1> 			     ; since 1/1/1970
  3067 00003991 668915[A66D0000]    <1> 	mov 	[hour], dx   ; leftover hours
  3068 00003998 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3069                              <1> 			     ; 1/1/1968 	
  3070                              <1> 	;mov 	[iday], ax
  3071 0000399D 50                  <1> 	push 	eax
  3072 0000399E 29D2                <1> 	sub	edx, edx
  3073 000039A0 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3074 000039A5 F7F1                <1> 	div	ecx
  3075 000039A7 59                  <1> 	pop 	ecx
  3076                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3077 000039A8 6652                <1> 	push 	dx
  3078                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3079 000039AA 6683FA3C            <1> 	cmp 	dx, 31 + 29  ; if past feb 29 then
  3080 000039AE F5                  <1> 	cmc		     ; add this quadyr's leap day
  3081 000039AF 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3082                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3083                              <1> 	;mov 	cx, [iday]
  3084 000039B2 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3085 000039B3 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3086 000039B5 B96D010000          <1> 	mov 	ecx, 365
  3087 000039BA 31D2                <1> 	xor	edx, edx
  3088                              <1> 	; EAX = iday-lday, EDX = 0
  3089 000039BC F7F1                <1> 	div	ecx
  3090                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3091                              <1> 	;jday = iday - (iyrs*365) - lday
  3092                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3093                              <1> 	;add	eax, 1968
  3094 000039BE 6605B007            <1> 	add 	ax, 1968     ; compute year
  3095 000039C2 66A3[A06D0000]      <1> 	mov 	[year], ax
  3096 000039C8 6689D1              <1> 	mov 	cx, dx
  3097                              <1> 	;mov 	dx, [qday]
  3098 000039CB 665A                <1> 	pop 	dx
  3099 000039CD 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3100 000039D2 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3101 000039D4 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3102 000039D8 F5                  <1>         cmc		     ; add a leap day to the # of whole
  3103 000039D9 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3104                              <1> cfe1:			
  3105                              <1> 	;mov 	[jday], cx
  3106 000039DD 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3107 000039E1 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3108 000039E5 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3109                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3110 000039E9 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3111 000039EC 731D                <1> 	jnb 	short cfe3
  3112 000039EE 664B                <1> 	dec 	bx           ; month = month - 1
  3113 000039F0 66D1E3              <1> 	shl 	bx, 1 
  3114 000039F3 668B93[AC6D0000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3115 000039FA 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3116 000039FD 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3117 00003A01 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3118 00003A03 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3119 00003A05 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3120 00003A07 6642                <1> 	inc 	dx           ; mday = mday + 1
  3121 00003A09 EBDE                <1> 	jmp 	short cfe2
  3122                              <1> cfe3:
  3123 00003A0B 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3124 00003A0D 66891D[A26D0000]    <1> 	mov 	[month], bx
  3125 00003A14 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3126 00003A17 6641                <1> 	inc 	cx 			  
  3127 00003A19 66890D[A46D0000]    <1> 	mov 	[day], cx
  3128                              <1> 	
  3129                              <1> 	; eax, ebx, ecx, edx is changed at return
  3130                              <1> 	; output ->
  3131                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3132                              <1> 	
  3133                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3134                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3135                              <1> set_date:
  3136 00003A20 A0[A16D0000]        <1>         mov     al, [year+1]
  3137 00003A25 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3138 00003A27 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3139                              <1> 			     ; AL = AH * 10h + AL
  3140 00003A29 88C5                <1> 	mov 	ch, al ; century (BCD)
  3141 00003A2B A0[A06D0000]        <1> 	mov 	al, [year]
  3142 00003A30 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3143 00003A32 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3144                              <1> 			     ; AL = AH * 10h + AL
  3145 00003A34 88C1                <1> 	mov 	cl, al ; year (BCD)
  3146 00003A36 A0[A26D0000]        <1>         mov 	al, [month]
  3147 00003A3B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3148 00003A3D D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3149                              <1> 			     ; AL = AH * 10h + AL
  3150 00003A3F 88C6                <1> 	mov 	dh, al ; month (BCD)
  3151 00003A41 A0[A46D0000]        <1> 	mov 	al, [day]
  3152 00003A46 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3153 00003A48 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3154                              <1> 			     ; AL = AH * 10h + AL
  3155 00003A4A 88C6                <1> 	mov 	dh, al ; day (BCD)
  3156                              <1> 	; Set real-time clock date
  3157 00003A4C E879000000          <1> 	call	set_rtc_date
  3158                              <1> set_time:
  3159                              <1>         ; Read real-time clock time 
  3160                              <1> 	; (get day light saving time bit status)
  3161 00003A51 FA                  <1>  	cli
  3162 00003A52 E8E0D1FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3163                              <1> 	; cf = 1 -> al = 0
  3164 00003A57 7207                <1>         jc      short stime1
  3165 00003A59 B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3166 00003A5B E8C1D1FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3167                              <1> stime1:
  3168 00003A60 FB                  <1> 	sti
  3169 00003A61 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3170 00003A63 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3171                              <1> 	; DL = 1 or 0 (day light saving time)
  3172                              <1> 	;	
  3173 00003A65 A0[A66D0000]        <1> 	mov 	al, [hour]
  3174 00003A6A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3175 00003A6C D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3176                              <1> 			     ; AL = AH * 10h + AL
  3177 00003A6E 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3178 00003A70 A0[A86D0000]        <1>         mov     al, [minute]
  3179 00003A75 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3180 00003A77 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3181                              <1> 			     ; AL = AH * 10h + AL
  3182 00003A79 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3183 00003A7B A0[AA6D0000]        <1>         mov     al, [second]
  3184 00003A80 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3185 00003A82 D510                <1> 	db 	0D5h,10h     ; Undocumented inst. AAD
  3186                              <1> 			     ; AL = AH * 10h + AL
  3187 00003A84 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3188                              <1> 	; Set real-time clock time
  3189                              <1>  	; call	set_rtc_time
  3190                              <1> set_rtc_time:
  3191                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3192                              <1> 	; 15/03/2015
  3193                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3194                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3195                              <1> 	; INT 1Ah
  3196                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3197                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3198                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3199                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3200                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3201                              <1> 	;								:
  3202                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3203                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3204                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3205                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3206                              <1> 	;
  3207                              <1> RTC_30: 				; SET RTC TIME
  3208 00003A86 FA                  <1> 	cli
  3209 00003A87 E8ABD1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3210 00003A8C 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3211 00003A8E E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3212                              <1> RTC_35:
  3213 00003A93 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3214 00003A95 B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3215 00003A97 E89E000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3216 00003A9C 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3217 00003A9E B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3218 00003AA0 E895000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3219 00003AA5 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3220 00003AA7 B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3221 00003AA9 E88C000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3222                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3223 00003AAE 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3224 00003AB2 E86AD1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3225 00003AB7 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3226 00003AB9 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3227 00003ABB 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3228 00003ABE 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3229 00003AC0 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3230 00003AC2 E873000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3231 00003AC7 F8                  <1> 	CLC				; SET CY= 0
  3232 00003AC8 FB                  <1> 	sti
  3233 00003AC9 C3                  <1> 	RETn				; RETURN WITH CY= 0
  3234                              <1> 
  3235                              <1> set_rtc_date:
  3236                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3237                              <1> 	; 15/03/2015
  3238                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3239                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3240                              <1> 	; INT 1Ah
  3241                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3242                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3243                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3244                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3245                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3246                              <1> 	;
  3247                              <1> RTC_50: 				; SET RTC DATE
  3248 00003ACA FA                  <1> 	cli
  3249 00003ACB E867D1FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3250 00003AD0 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3251 00003AD2 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3252                              <1> RTC_55:
  3253 00003AD7 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3254 00003ADB E85A000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3255 00003AE0 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3256 00003AE2 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3257 00003AE4 E851000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3258 00003AE9 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3259 00003AEB B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3260 00003AED E848000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3261 00003AF2 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3262 00003AF4 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3263 00003AF6 E83F000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3264 00003AFB 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3265 00003AFD B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3266 00003AFF E836000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3267                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3268 00003B04 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3269 00003B08 E814D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3270 00003B0D 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3271 00003B0F 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3272 00003B11 E824000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3273 00003B16 F8                  <1> 	CLC				; SET CY= 0
  3274 00003B17 FB                  <1> 	sti
  3275 00003B18 C3                  <1> 	RETn				; RETURN CY=0
  3276                              <1> 
  3277                              <1> 	; 15/03/2015
  3278                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3279 00003B19 B426                <1> 	mov	ah, 26h
  3280 00003B1B B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3281 00003B1D E818000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3282 00003B22 B482                <1> 	mov	ah, 82h
  3283 00003B24 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3284 00003B26 E80F000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3285 00003B2B B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3286 00003B2D E8EFD0FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3287 00003B32 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3288 00003B34 E8E8D0FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3289 00003B39 C3                  <1> 	RETn
  3290                              <1> 
  3291                              <1> 	; 15/03/2015
  3292                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3293                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3294 00003B3A 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3295                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3296 00003B3B D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3297 00003B3D F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3298 00003B3E D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3299 00003B40 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3300 00003B41 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3301 00003B43 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3302 00003B45 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3303 00003B47 B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3304 00003B49 D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3305 00003B4B E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3306 00003B4D 90                  <1> 	nop			; I/O DELAY
  3307 00003B4E E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3308                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3309 00003B50 9D                  <1> 	popf	
  3310 00003B51 C3                  <1> 	RETn
  3311                              <1> 
  3312                              <1> bf_init:
  3313                              <1> 	; 28/11/2021
  3314                              <1> 	; 14/08/2015
  3315                              <1> 	; 02/07/2015
  3316                              <1> 	; 01/07/2015
  3317                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3318                              <1> 	; Buffer (pointer) initialization !
  3319                              <1> 	; 
  3320                              <1> 	; 17/07/2013 - 24/07/2013
  3321                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3322                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3323                              <1> 	;
  3324 00003B52 BF[F0700000]        <1> 	mov	edi, bufp 
  3325 00003B57 B8[68820000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3326 00003B5C 29D2                <1> 	sub	edx, edx
  3327 00003B5E FECA                <1> 	dec	dl
  3328 00003B60 31C9                <1> 	xor	ecx, ecx
  3329 00003B62 49                  <1> 	dec	ecx
  3330                              <1> bi0:
  3331 00003B63 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3332 00003B68 AB                  <1> 	stosd
  3333 00003B69 89C6                <1> 	mov	esi, eax
  3334 00003B6B 8916                <1> 	mov	[esi], edx ; 000000FFh
  3335                              <1> 			    ; Not a valid device sign
  3336 00003B6D 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3337                              <1> 		      ; Not a valid block number sign 	 	
  3338 00003B70 3D[38760000]        <1> 	cmp	eax, buffer
  3339 00003B75 77EC                <1> 	ja	short bi0
  3340 00003B77 B8[0C720000]        <1> 	mov	eax, sb0
  3341 00003B7C AB                  <1> 	stosd
  3342 00003B7D B8[14740000]        <1> 	mov	eax, sb1
  3343 00003B82 AB                  <1> 	stosd
  3344 00003B83 89C6                <1> 	mov	esi, eax ; offset sb1
  3345 00003B85 8916                <1> 	mov	[esi], edx ; 000000FFh
  3346                              <1> 			    ; Not a valid device sign
  3347 00003B87 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3348                              <1> 		      ; Not a valid block number sign 	 
  3349                              <1> 	; 14/08/2015
  3350                              <1> 	;call 	rdev_init
  3351                              <1> 	;retn
  3352                              <1> 
  3353                              <1> 	; 28/11/2021
  3354                              <1> rdev_init: ; root device, super block buffer initialization
  3355                              <1> 	; 14/08/2015
  3356                              <1> 	; Retro UNIX 386 v1 feature only !
  3357                              <1> 	;
  3358                              <1> 	; NOTE: Disk partitions (file systems), logical
  3359                              <1> 	; drive initialization, partition's start sector etc.
  3360                              <1> 	; will be coded here, later in 'ldrv_init'	
  3361                              <1> 
  3362 00003B8A 0FB605[2A6B0000]    <1> 	movzx	eax, byte [boot_drv]
  3363                              <1> rdi_0:
  3364 00003B91 3C80                <1> 	cmp	al, 80h
  3365 00003B93 7202                <1> 	jb	short rdi_1
  3366 00003B95 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3367                              <1> rdi_1:
  3368                              <1> ; temporary - 05/12/2021
  3369 00003B97 20C0                <1> and	al, al
  3370 00003B99 7515                <1> jnz	short rdi_2
  3371 00003B9B C605[506B0000]12    <1> mov	byte [drv.spt], 18
  3372 00003BA2 C605[426B0000]02    <1> mov	byte [drv.heads], 2
  3373 00003BA9 C605[346B0000]50    <1> mov	byte [drv.cylinders], 80
  3374                              <1> rdi_2:
  3375 00003BB0 A2[16710000]        <1> 	mov	[rdev], al
  3376 00003BB5 BB[0C720000]        <1>         mov	ebx, sb0 ; super block buffer
  3377 00003BBA 8903                <1> 	mov 	[ebx], eax
  3378 00003BBC B001                <1> 	mov	al, 1 ; eax = 1
  3379 00003BBE 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3380                              <1> 	;call 	diskio
  3381                              <1> 	;retn
  3382                              <1> 	; 28/11/2021
  3383 00003BC1 E9AA270000          <1> 	jmp	diskio
  3384                              <1> 
  3385                              <1> ; 23/10/2015
  3386                              <1> com1_irq4:
  3387 00003BC6 [CE3B0000]          <1> 	dd dummy_retn
  3388                              <1> com2_irq3:
  3389 00003BCA [CE3B0000]          <1> 	dd dummy_retn
  3390                              <1> 
  3391                              <1> dummy_retn:
  3392 00003BCE C3                  <1> 	retn
  2020                                  %include 'u1.s'      ; 10/05/2015
  2021                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2022                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2023                              <1> ; ****************************************************************************
  2024                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS1.INC
  2025                              <1> ; Last Modification: 25/12/2021
  2026                              <1> ; ----------------------------------------------------------------------------
  2027                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2028                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2029                              <1> ;
  2030                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2031                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2032                              <1> ; <Bell Laboratories (17/3/1972)>
  2033                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2034                              <1> ;
  2035                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2036                              <1> ;
  2037                              <1> ; ****************************************************************************
  2038                              <1> 
  2039                              <1> unkni: ; / used for all system calls
  2040                              <1> sysent: ; < enter to system call >
  2041                              <1> 	; 25/12/2021 (Retro UNIX 386 v1.2)
  2042                              <1> 	; 19/10/2015
  2043                              <1> 	; 21/09/2015
  2044                              <1> 	; 01/07/2015
  2045                              <1> 	; 19/05/2015
  2046                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2047                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2048                              <1> 	;
  2049                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2050                              <1> 	; The trap type is determined and an indirect jump is made to 
  2051                              <1> 	; the appropriate system call handler. If there is a trap inside
  2052                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2053                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2054                              <1> 	; instructor is decoded to get the the system code part (see
  2055                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2056                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2057                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2058                              <1> 	; is called. If the call is legitimate control passes to the
  2059                              <1> 	; appropriate system routine.
  2060                              <1> 	;
  2061                              <1> 	; Calling sequence:
  2062                              <1> 	;	Through a trap caused by any sys call outside the system.
  2063                              <1> 	; Arguments:
  2064                              <1> 	;	Arguments of particular system call.	
  2065                              <1> 	; ...............................................................
  2066                              <1> 	;	
  2067                              <1> 	; Retro UNIX 8086 v1 modification: 
  2068                              <1> 	;       System call number is in EAX register.
  2069                              <1> 	;
  2070                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2071                              <1> 	;	registers depending of function details.
  2072                              <1>   	;
  2073                              <1> 	; 16/04/2015
  2074 00003BCF 368925[2C710000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2075                              <1> 	; save user registers
  2076 00003BD6 1E                  <1> 	push	ds
  2077 00003BD7 06                  <1> 	push	es
  2078 00003BD8 0FA0                <1> 	push	fs
  2079 00003BDA 0FA8                <1> 	push	gs
  2080 00003BDC 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2081                              <1> 	;
  2082                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2083                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2084                              <1> 	;	for saving/restoring user registers.)
  2085                              <1> 	;
  2086 00003BDD 50                  <1> 	push	eax ; 01/07/2015
  2087 00003BDE 66B81000            <1> 	mov     ax, KDATA
  2088 00003BE2 8ED8                <1>         mov     ds, ax
  2089 00003BE4 8EC0                <1>         mov     es, ax
  2090 00003BE6 8EE0                <1>         mov     fs, ax
  2091 00003BE8 8EE8                <1>         mov     gs, ax
  2092 00003BEA A1[38700000]        <1> 	mov	eax, [k_page_dir]
  2093 00003BEF 0F22D8              <1> 	mov	cr3, eax
  2094 00003BF2 58                  <1> 	pop	eax ; 01/07/2015
  2095                              <1> 	; 19/10/2015
  2096 00003BF3 FC                  <1> 	cld
  2097                              <1> 	;
  2098 00003BF4 FE05[29710000]      <1> 	inc	byte [sysflg]
  2099                              <1> 		; incb sysflg / indicate a system routine is in progress
  2100 00003BFA FB                  <1>         sti 	; 18/01/2014
  2101                              <1> 	;jnz     panic ; 24/05/2013
  2102                              <1> 	; 04/12/2021
  2103 00003BFB 7405                <1> 	jz	short _1
  2104 00003BFD E94CF9FFFF          <1> 	jmp	panic
  2105                              <1> 		; beq 1f
  2106                              <1> 		; jmp panic ; / called if trap inside system
  2107                              <1> ;1:
  2108                              <1> _1:	; 04/12/2021
  2109                              <1> 	; 16/04/2015
  2110 00003C02 A3[34710000]        <1> 	mov	[u.r0], eax
  2111 00003C07 8925[30710000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2112                              <1> 	;
  2113                              <1> 		; mov $s.syst+2,clockp
  2114                              <1> 		; mov r0,-(sp) / save user registers 
  2115                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2116                              <1> 			   ; / in u.r0
  2117                              <1> 		; mov r1,-(sp)
  2118                              <1> 		; mov r2,-(sp)
  2119                              <1> 		; mov r3,-(sp)
  2120                              <1> 		; mov r4,-(sp)
  2121                              <1> 		; mov r5,-(sp)
  2122                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2123                              <1> 		             ; / arithmetic unit
  2124                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2125                              <1> 		             ; / extended arithmetic unit
  2126                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2127                              <1> 		             ; / arithmetic unit
  2128                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2129                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2130                              <1> 		; mov -(r0),r0 / sys inst in r0 10400xxx
  2131                              <1> 		; sub $sys,r0 / get xxx code
  2132 00003C0D C1E002              <1> 	shl	eax, 2
  2133                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2134 00003C10 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2135                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2136                              <1> 	;jnb	short badsys
  2137                              <1> 		; bhis badsys / yes, bad system call
  2138                              <1> 	; 25/12/2021
  2139 00003C15 7205                <1> 	jb	short _2
  2140 00003C17 E95D010000          <1> 	jmp	badsys
  2141                              <1> _2:
  2142                              <1> 	; 25/12/2021
  2143                              <1> 	;cmc
  2144                              <1> 	;pushf	
  2145                              <1> 	;push	eax
  2146 00003C1C 8B2D[2C710000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2147                              <1> 	;mov	al, 0FEh ; 11111110b
  2148                              <1> 	;;adc	al, 0 ; al = al + cf
  2149                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2150 00003C22 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2151                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2152                              <1> 				 ; / and clear carry bit
  2153                              <1> 	;pop	ebp ; eax
  2154 00003C26 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2155                              <1> 	;popf
  2156                              <1>         ;;jc	badsys
  2157                              <1> 	;; 04/12/2021
  2158                              <1> 	;jnc	short _3
  2159                              <1> 	;jmp	badsys
  2160                              <1> ;_3:
  2161 00003C28 A1[34710000]        <1> 	mov	eax, [u.r0]
  2162                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2163 00003C2D FFA5[333C0000]      <1> 	jmp	dword [ebp+syscalls]
  2164                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2165                              <1> 		            ; / to proper system routine.
  2166                              <1> syscalls: ; 1:
  2167                              <1> 	; 21/09/2015
  2168                              <1> 	; 01/07/2015
  2169                              <1> 	; 16/04/2015 (32 bit address modification) 
  2170 00003C33 [433D0000]          <1> 	dd sysrele	; / 0
  2171 00003C37 [FE3D0000]          <1> 	dd sysexit 	; / 1
  2172 00003C3B [2D3F0000]          <1> 	dd sysfork 	; / 2
  2173 00003C3F [3E400000]          <1> 	dd sysread 	; / 3
  2174 00003C43 [72400000]          <1> 	dd syswrite 	; / 4
  2175 00003C47 [0E410000]          <1> 	dd sysopen 	; / 5
  2176 00003C4B [AA420000]          <1> 	dd sysclose 	; / 6
  2177 00003C4F [AF3E0000]          <1> 	dd syswait 	; / 7
  2178 00003C53 [24420000]          <1> 	dd syscreat 	; / 8
  2179 00003C57 [BD450000]          <1> 	dd syslink 	; / 9
  2180 00003C5B [7B460000]          <1> 	dd sysunlink 	; / 10
  2181 00003C5F [45470000]          <1> 	dd sysexec 	; / 11
  2182 00003C63 [C64D0000]          <1> 	dd syschdir 	; / 12
  2183 00003C67 [AA4E0000]          <1> 	dd systime 	; / 13
  2184 00003C6B [7B420000]          <1> 	dd sysmkdir 	; / 14
  2185 00003C6F [184E0000]          <1> 	dd syschmod 	; / 15
  2186 00003C73 [7A4E0000]          <1> 	dd syschown 	; / 16
  2187 00003C77 [DD4E0000]          <1> 	dd sysbreak 	; / 17
  2188 00003C7B [0A4B0000]          <1> 	dd sysstat 	; / 18
  2189 00003C7F [A24F0000]          <1> 	dd sysseek 	; / 19
  2190 00003C83 [B44F0000]          <1> 	dd systell 	; / 20
  2191 00003C87 [1F5D0000]          <1> 	dd sysmount 	; / 21
  2192 00003C8B [D15D0000]          <1> 	dd sysumount 	; / 22
  2193 00003C8F [32500000]          <1> 	dd syssetuid 	; / 23
  2194 00003C93 [63500000]          <1> 	dd sysgetuid 	; / 24
  2195 00003C97 [B94E0000]          <1> 	dd sysstime 	; / 25
  2196 00003C9B [26500000]          <1> 	dd sysquit 	; / 26
  2197 00003C9F [1A500000]          <1> 	dd sysintr 	; / 27
  2198 00003CA3 [EE4A0000]          <1> 	dd sysfstat 	; / 28
  2199 00003CA7 [C5420000]          <1> 	dd sysemt 	; / 29
  2200 00003CAB [F3420000]          <1> 	dd sysmdate 	; / 30
  2201 00003CAF [42430000]          <1> 	dd sysstty 	; / 31
  2202 00003CB3 [B0440000]          <1> 	dd sysgtty 	; / 32
  2203 00003CB7 [EE420000]          <1> 	dd sysilgins 	; / 33
  2204 00003CBB [4B660000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2205                              <1> 			     ; 11/06/2014
  2206 00003CBF [78660000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2207                              <1> 			     ; 01/07/2015
  2208 00003CC3 [50670000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2209                              <1> 			     ; 21/09/2015 - get last error number
  2210                              <1> end_of_syscalls:
  2211                              <1> 
  2212                              <1> error:
  2213                              <1> 	; 11/12/2021 (Retro UNIX 386 v1.2)
  2214                              <1> 	; 17/09/2015
  2215                              <1> 	; 03/09/2015
  2216                              <1> 	; 01/09/2015
  2217                              <1> 	; 09/06/2015
  2218                              <1> 	; 13/05/2015
  2219                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2220                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2221                              <1> 	;
  2222                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2223                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2224                              <1> 	;
  2225                              <1> 	; INPUTS -> none
  2226                              <1> 	; OUTPUTS ->
  2227                              <1> 	;	processor status - carry (c) bit is set (means error)
  2228                              <1> 	;
  2229                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2230                              <1> 	; 	      Because, jumps to error procedure
  2231                              <1> 	;	      disrupts push-pop nesting balance)
  2232                              <1> 	;
  2233 00003CC7 8B2D[2C710000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2234 00003CCD 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2235                              <1> 				 ; (system call will return with cf = 1)
  2236                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2237                              <1> 		               ; / users stack
  2238                              <1> 	; 17/09/2015
  2239 00003CD1 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2240                              <1> 				 ; for saving/restoring user registers	
  2241                              <1> 	;cmp	ebp, [u.usp]
  2242                              <1> 	;je	short err0	
  2243 00003CD4 892D[30710000]      <1> 	mov	[u.usp], ebp
  2244                              <1> ;err0:
  2245                              <1> 	; 01/09/2015
  2246 00003CDA 8B25[30710000]      <1> 	mov	esp, [u.usp]	; Retro Unix 8086 v1 modification!
  2247                              <1> 				; 10/04/2013
  2248                              <1> 				; (If an I/O error occurs during disk I/O,
  2249                              <1> 				; related procedures will jump to 'error'
  2250                              <1> 				; procedure directly without returning to 
  2251                              <1> 				; the caller procedure. So, stack pointer
  2252                              <1> 				; must be restored here.)
  2253                              <1> 	; 13/05/2015
  2254                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2255                              <1> 	;	'get last error' system call later. 	
  2256                              <1> 
  2257                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2258 00003CE0 C605[AA710000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2259                              <1> 
  2260                              <1> sysret: ; < return from system call>
  2261                              <1> 	; 11/12/2021
  2262                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2263                              <1> 	; 30/11/2021
  2264                              <1> 	; 10/09/2015
  2265                              <1> 	; 29/07/2015
  2266                              <1> 	; 25/06/2015
  2267                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2268                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2269                              <1> 	;
  2270                              <1> 	; 'sysret' first checks to see if process is about to be 
  2271                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2272                              <1> 	; If not, following happens:	 
  2273                              <1> 	; 	1) The user's stack pointer is restored.
  2274                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2275                              <1> 	;	   i-node has been modified. If it has, it is written out
  2276                              <1> 	;	   via 'ppoke'.
  2277                              <1> 	;	3) If the super block has been modified, it is written out
  2278                              <1> 	;	   via 'ppoke'.				
  2279                              <1> 	;	4) If the dismountable file system's super block has been
  2280                              <1> 	;	   modified, it is written out to the specified device
  2281                              <1> 	;	   via 'ppoke'.
  2282                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2283                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2284                              <1> 	;	   another user a chance to run.
  2285                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2286                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2287                              <1> 	;
  2288                              <1> 	; Calling sequence:
  2289                              <1> 	;	jump table or 'br sysret'
  2290                              <1> 	; Arguments: 
  2291                              <1> 	;	-	
  2292                              <1> 	; ...............................................................
  2293                              <1> 	;	
  2294                              <1> 	; ((AX=r1 for 'iget' input))
  2295                              <1> 	;	
  2296                              <1> 	;xor	ax, ax ; 04/05/2013
  2297                              <1> 	; 30/11/2021
  2298 00003CE7 31C0                <1> 	xor	eax, eax
  2299                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2300 00003CE9 FEC0                <1> 	inc	al ; 04/05/2013
  2301 00003CEB 3805[88710000]      <1> 	cmp	[u.bsys], al ; 1
  2302                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2303                              <1> 	;jnb	sysexit ; 04/05/2013
  2304                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2305                              <1> 	; 04/12/2021
  2306 00003CF1 720F                <1> 	jb	short _3
  2307                              <1> 	; 11/12/2021
  2308 00003CF3 C705[AC710000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2308 00003CFB 0000                <1>
  2309 00003CFD E9FC000000          <1> 	jmp	sysexit
  2310                              <1> _3:
  2311                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2312                              <1> 		; mov u.sp,sp / no point stack to users stack
  2313 00003D02 FEC8                <1> 	dec 	al ; mov ax, 0
  2314                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2315 00003D04 E8DE180000          <1> 	call	iget
  2316                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2317                              <1> 		            ; / it is written out
  2318                              <1> 	;xor 	ax, ax ; 0
  2319                              <1> 	; 30/11/2021
  2320 00003D09 31C0                <1> 	xor	eax, eax
  2321 00003D0B 3805[27710000]      <1> 	cmp	[smod], al ; 0
  2322                              <1> 		; tstb	smod / has the super block been modified
  2323 00003D11 7614                <1> 	jna	short sysret1
  2324                              <1> 		; beq	1f / no, 1f
  2325 00003D13 A2[27710000]        <1> 	mov	[smod], al ; 0
  2326                              <1> 		; clrb smod / yes, clear smod
  2327 00003D18 BB[0C720000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2328 00003D1D 66810B0002          <1>    	or	word [ebx], 200h ;;
  2329                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2330                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2331                              <1> 		      	      ; / output
  2332                              <1> 	; AX = 0
  2333 00003D22 E827250000          <1> 	call 	poke ; 07/08/2013
  2334                              <1> 	;call	ppoke
  2335                              <1> 	; AX = 0
  2336                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2337                              <1> sysret1: ;1:
  2338 00003D27 3805[28710000]      <1> 	cmp	[mmod], al ; 0
  2339                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2340                              <1> 		           ; / system
  2341 00003D2D 7614                <1> 	jna	short sysrel0
  2342                              <1> 		; beq 1f / been modified?  no, 1f
  2343 00003D2F A2[28710000]        <1> 	mov	[mmod], al ; 0	
  2344                              <1> 		; clrb	mmod / yes, clear mmod
  2345                              <1>         ;mov    ax, [mntd]
  2346                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2347 00003D34 BB[14740000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2348                              <1>         ;;mov	[ebx], al
  2349                              <1> 	;mov    [sb1], al
  2350                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2351 00003D39 66810B0002          <1> 	or	word [ebx], 200h
  2352                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2353                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2354 00003D3E E80B250000          <1> 	call	poke ; 07/08/2013
  2355                              <1> 	;call	ppoke 
  2356                              <1> 		; jsr r0,ppoke / write it out to its device
  2357                              <1>         ;xor    al, al ; 26/04/2013       
  2358                              <1> ;1:
  2359                              <1> 		; tstb uquant / is the time quantum 0?
  2360                              <1> 		; bne 1f / no, don't swap it out
  2361                              <1> 
  2362                              <1> sysrele: ; < release >
  2363                              <1> 	; 14/10/2015
  2364                              <1> 	; 01/09/2015
  2365                              <1> 	; 24/07/2015
  2366                              <1> 	; 14/05/2015
  2367                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2368                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2369                              <1> 	;
  2370                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2371                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2372                              <1> 	; turns off the system flag. It then checked to see if there is
  2373                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2374                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2375                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2376                              <1> 	; the user, a rti is made.
  2377                              <1> 	;
  2378                              <1> 	; Calling sequence:
  2379                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2380                              <1> 	; Arguments:
  2381                              <1> 	;	-	
  2382                              <1> 	; ...............................................................
  2383                              <1> 	;	
  2384                              <1> 	; 23/02/2014 (swapret)
  2385                              <1> 	; 22/09/2013
  2386                              <1> sysrel0: ;1:
  2387 00003D43 803D[80710000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2388                              <1> 		; tstb uquant / is the time quantum 0?
  2389 00003D4A 7705                <1>         ja      short swapret
  2390                              <1> 		; bne 1f / no, don't swap it out
  2391                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2392 00003D4C E855130000          <1> 	call	tswap
  2393                              <1> 		; jsr r0,tswap / yes, swap it out
  2394                              <1> ;
  2395                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2396                              <1> swapret: ;1:
  2397                              <1> 	; 10/09/2015
  2398                              <1> 	; 01/09/2015
  2399                              <1> 	; 14/05/2015
  2400                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2401                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2402                              <1> 	; cli
  2403                              <1> 	; 24/07/2015
  2404                              <1> 	;
  2405                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2406                              <1> 	;; mov	esp, [u.usp]
  2407                              <1> 
  2408                              <1> 	; 22/09/2013
  2409 00003D51 E835150000          <1> 	call	isintr
  2410                              <1> 	; 20/10/2013
  2411 00003D56 7405                <1> 	jz	short sysrel1
  2412 00003D58 E88A000000          <1> 	call	intract
  2413                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2414                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2415                              <1> 		               ; / action
  2416                              <1> sysrel1:
  2417 00003D5D FA                  <1> 	cli ; 14/10/2015
  2418 00003D5E FE0D[29710000]      <1> 	dec	byte [sysflg]
  2419                              <1> 		; decb sysflg / turn system flag off
  2420 00003D64 A1[98710000]        <1> 	mov     eax, [u.pgdir]
  2421 00003D69 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2422                              <1> 			  ; (others are different than kernel page tables) 
  2423                              <1> 	; 10/09/2015
  2424 00003D6C 61                  <1> 	popad ; edi, esi, ebp, temp (increment esp by 4), ebx, edx, ecx, eax
  2425                              <1> 		; mov (sp)+,sc / restore user registers
  2426                              <1> 		; mov (sp)+,mq
  2427                              <1> 		; mov (sp)+,ac
  2428                              <1> 		; mov (sp)+,r5
  2429                              <1> 		; mov (sp)+,r4
  2430                              <1> 		; mov (sp)+,r3
  2431                              <1> 		; mov (sp)+,r2
  2432                              <1> 	;
  2433 00003D6D A1[34710000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2434 00003D72 0FA9                <1> 	pop	gs
  2435 00003D74 0FA1                <1> 	pop	fs
  2436 00003D76 07                  <1> 	pop	es
  2437 00003D77 1F                  <1> 	pop	ds
  2438 00003D78 CF                  <1> 	iretd	
  2439                              <1> 		; rti / no, return from interrupt
  2440                              <1> 
  2441                              <1> badsys:
  2442                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2443                              <1> 	; (Major Modification: 'core' dumping procedure in
  2444                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2445                              <1> 	;	has been changed to print 'Invalid System Call !'
  2446                              <1> 	;	message on the user's console tty.)
  2447                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2448                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2449                              <1> 	; (EAX = Function number)  
  2450                              <1> 	;
  2451 00003D79 FE05[88710000]      <1> 	inc	byte [u.bsys]
  2452                              <1> 	;
  2453 00003D7F 8B1D[2C710000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2454 00003D85 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2455 00003D87 E821DBFFFF          <1> 	call	dwordtohex
  2456 00003D8C 8915[946D0000]      <1> 	mov	[bsys_msg_eip], edx
  2457 00003D92 A3[986D0000]        <1> 	mov	[bsys_msg_eip+4], eax
  2458 00003D97 A1[34710000]        <1> 	mov	eax, [u.r0]
  2459 00003D9C E80CDBFFFF          <1> 	call	dwordtohex
  2460 00003DA1 8915[846D0000]      <1> 	mov	[bsys_msg_eax], edx
  2461 00003DA7 A3[886D0000]        <1> 	mov	[bsys_msg_eax+4], eax
  2462                              <1> 	; 11/12/2021
  2463                              <1> 	;xor	eax, eax
  2464                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2465                              <1> 	;mov	ebx, [u.fofp]
  2466                              <1> 	;mov	[ebx], eax
  2467                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2468                              <1> 	;inc	eax
  2469                              <1> 	; 11/12/2021 - Retro UNIX 386 v2 fs compatibility 
  2470                              <1> 	; (Retro UNIX 386 v1.2)
  2471                              <1> 	;mov	al, 8 ; /dev/tty inode number (runix v2 fs)
  2472                              <1> 	;; eax = 8 ; inode number of console tty (for user)	
  2473                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2474                              <1> 		; writei
  2475                              <1> 		; INPUTS ->
  2476                              <1> 		;    r1 - inode number
  2477                              <1> 		;    u.count - byte count to be written
  2478                              <1> 		;    u.base - points to user buffer
  2479                              <1> 		;    u.fofp - points to word with current file offset
  2480                              <1> 		; OUTPUTS ->
  2481                              <1> 		;    u.count - cleared
  2482                              <1> 		;    u.nread - accumulates total bytes passed back	
  2483                              <1> 		;
  2484                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2485                              <1> 	;call	writei
  2486                              <1> 	;;mov	eax, 1
  2487                              <1> 	;jmp	sysexit
  2488                              <1> 
  2489                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2490 00003DAC BE[656D0000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2491 00003DB1 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2492                              <1> ; temporary - 12/12/2021
  2493                              <1> ;mov bl, 1
  2494 00003DB8 8A83[6F6E0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2495                              <1> ;mov al, 0
  2496 00003DBE C605[67700000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2497 00003DC5 A2[6D710000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2498 00003DCA E866290000          <1> 	call	print_cmsg
  2499                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2500                              <1> 
  2501                              <1> ; temporary - 11/12/2021
  2502 00003DCF C70500800B00324E32- <1> mov dword [0B8000h], 4E324E32h
  2502 00003DD8 4E                  <1>
  2503 00003DD9 B9FFFF0000          <1> mov ecx, 0FFFFh
  2504                              <1> abovexfx:
  2505 00003DDE 4A                  <1> dec edx
  2506 00003DDF 42                  <1> inc edx
  2507 00003DE0 E2FC                <1> loop abovexfx
  2508                              <1> 
  2509 00003DE2 E9E0FEFFFF          <1> 	jmp	error
  2510                              <1> 
  2511                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2512                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2513                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2514                              <1> 		; br 1f / error
  2515                              <1> 		; neg r1 / negate the i-number to open the core image file
  2516                              <1> 		       ; / for writing
  2517                              <1> 		; jsr r0,iopen / open the core image file
  2518                              <1> 		; jsr r0,itrunc / free all associated blocks
  2519                              <1> 		; br 2f
  2520                              <1> ;1:
  2521                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2522                              <1> 		; jsr r0,maknod / make an i-node
  2523                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2524                              <1> ;2:
  2525                              <1> 		; mov $core,u.base / move address core to u.base
  2526                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2527                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2528                              <1> 		; clr u.off / clear user offset
  2529                              <1> 		; jsr r0,writei / write out the core image to the user
  2530                              <1> 		; mov $user,u.base / pt. u.base to user
  2531                              <1> 		; mov $64.,u.count / u.count = 64
  2532                              <1> 		; jsr r0,writei / write out all the user parameters
  2533                              <1> 		; neg r1 / make i-number positive
  2534                              <1> 		; jsr r0,iclose / close the core image file
  2535                              <1> 		; br sysexit /
  2536                              <1> ;3:
  2537                              <1> 		; <core\0\0>
  2538                              <1> 
  2539                              <1> intract: ; / interrupt action
  2540                              <1> 	; 14/10/2015
  2541                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2542                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2543                              <1> 	;
  2544                              <1> 	; Retro UNIX 8086 v1 modification !
  2545                              <1> 	; (Process/task switching and quit routine by using
  2546                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2547                              <1> 	;
  2548                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2549                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2550                              <1> 	;		'intract' will jump to 'sysexit'.
  2551                              <1> 	;	    Intract will return to the caller 
  2552                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2553                              <1> 	; 14/10/2015
  2554 00003DE7 FB                  <1> 	sti
  2555                              <1> 	; 07/12/2013	
  2556 00003DE8 66FF05[86710000]    <1> 	inc 	word [u.quit]
  2557 00003DEF 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2558 00003DF1 66FF0D[86710000]    <1> 	dec	word [u.quit]
  2559                              <1> 	; 16/04/2015
  2560 00003DF8 C3                  <1> 	retn
  2561                              <1> intrct0:	
  2562 00003DF9 58                  <1> 	pop	eax ; call intract -> retn
  2563                              <1> 	;
  2564 00003DFA 31C0                <1> 	xor 	eax, eax
  2565 00003DFC FEC0                <1> 	inc	al  ; mov ax, 1
  2566                              <1> ;;;
  2567                              <1> 	; UNIX v1 original 'intract' routine... 
  2568                              <1> 	; / interrupt action
  2569                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2570                              <1> 		; bne 1f / no, 1f
  2571                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2572                              <1> 	; 1: / now in user area
  2573                              <1> 		; mov r1,-(sp) / save r1
  2574                              <1> 		; mov u.ttyp,r1 
  2575                              <1> 			; / pointer to tty buffer in control-to r1
  2576                              <1> 		; cmpb 6(r1),$177
  2577                              <1> 			; / is the interrupt char equal to "del"
  2578                              <1> 		; beq 1f / yes, 1f
  2579                              <1> 		; clrb 6(r1) 
  2580                              <1> 		        ; / no, clear the byte 
  2581                              <1> 			; / (must be a quit character)
  2582                              <1> 		; mov (sp)+,r1 / restore r1
  2583                              <1> 		; clr u.quit / clear quit flag
  2584                              <1> 		; bis $20,2(sp) 
  2585                              <1> 		    	; / set trace for quit (sets t bit of 
  2586                              <1> 			; / ps-trace trap)
  2587                              <1> 		; rti   ;  / return from interrupt
  2588                              <1> 	; 1: / interrupt char = del
  2589                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2590                              <1> 			   ; / in the buffer
  2591                              <1> 		; mov (sp)+,r1 / restore r1
  2592                              <1> 		; cmp u.intr,$core / should control be 
  2593                              <1> 				; / transferred to loc core?
  2594                              <1> 		; blo 1f
  2595                              <1> 		; jmp *u.intr / user to do rti yes, 
  2596                              <1> 				; / transfer to loc core
  2597                              <1> 	; 1:
  2598                              <1> 		; sys 1 / exit
  2599                              <1> 
  2600                              <1> sysexit: ; <terminate process>
  2601                              <1> 	; 30/11/2021 - etro UNIX 386 v1.2
  2602                              <1> 	; 01/09/2015
  2603                              <1> 	; 31/08/2015
  2604                              <1> 	; 14/05/2015
  2605                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2606                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2607                              <1> 	;
  2608                              <1> 	; 'sysexit' terminates a process. First each file that
  2609                              <1> 	; the process has opened is closed by 'flose'. The process
  2610                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2611                              <1> 	; searched to find children of the dying process. If any of
  2612                              <1> 	; children are zombies (died by not waited for), they are
  2613                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2614                              <1> 	; dying process's parent. When the parent is found, it is
  2615                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2616                              <1> 	; one of these, the dying process just dies. If it is waiting
  2617                              <1> 	; for a child process to die, it notified that it doesn't 
  2618                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2619                              <1> 	; (waiting to active). It is awakened and put on runq by
  2620                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2621                              <1> 	; it will never be run again but stays around until a 'wait'
  2622                              <1> 	; is completed by it's parent process. If the parent is not
  2623                              <1> 	; found, process just dies. This means 'swap' is called with
  2624                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2625                              <1> 	; to write out the process and 'rswap' reads the new process
  2626                              <1> 	; over the one that dies..i.e., the dying process is 
  2627                              <1> 	; overwritten and destroyed.	
  2628                              <1>  	;
  2629                              <1> 	; Calling sequence:
  2630                              <1> 	;	sysexit or conditional branch.
  2631                              <1> 	; Arguments:
  2632                              <1> 	;	-	
  2633                              <1> 	; ...............................................................
  2634                              <1> 	;	
  2635                              <1> 	; Retro UNIX 8086 v1 modification: 
  2636                              <1> 	;       System call number (=1) is in EAX register.
  2637                              <1> 	;
  2638                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2639                              <1> 	;       registers depending of function details.
  2640                              <1> 	;
  2641                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2642                              <1> 	;
  2643                              <1> ; / terminate process
  2644                              <1> 	; AX = 1
  2645                              <1> 	;dec 	ax ; 0
  2646                              <1> 	; 30/11/2021
  2647 00003DFE 48                  <1> 	dec	eax ; 0
  2648 00003DFF 66A3[84710000]      <1> 	mov	[u.intr], ax ; 0
  2649                              <1> 		; clr u.intr / clear interrupt control word
  2650                              <1> 		; clr r1 / clear r1
  2651                              <1> 
  2652                              <1> ; temporary - 26/12/2021
  2653 00003E05 B9FFFF0000          <1> mov ecx, 0FFFFh
  2654                              <1> fcloop:
  2655 00003E0A 48                  <1> dec	eax
  2656 00003E0B 40                  <1> inc	eax
  2657 00003E0C 4A                  <1> dec	edx
  2658 00003E0D 42                  <1> inc	edx
  2659 00003E0E E2FA                <1> loop	fcloop
  2660                              <1> 
  2661                              <1> 	; AX = 0
  2662                              <1> sysexit_1: ; 1:
  2663                              <1> 	; AX = File descriptor
  2664                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2665                              <1> 		; / Search the whole list
  2666 00003E10 E8880D0000          <1> 	call	fclose
  2667                              <1> 		; jsr r0,fclose / close all files the process opened
  2668                              <1> 	;; ignore error return
  2669                              <1> 		; br .+2 / ignore error return
  2670                              <1> 	;inc	ax
  2671 00003E15 FEC0                <1> 	inc	al
  2672                              <1> 		; inc r1 / increment file descriptor
  2673                              <1> 	;cmp	ax, 10
  2674 00003E17 3C0A                <1> 	cmp	al, 10
  2675                              <1> 		; cmp r1,$10. / end of u.fp list?
  2676 00003E19 72F5                <1> 	jb	short sysexit_1
  2677                              <1> 		; blt 1b / no, go back
  2678 00003E1B 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2679                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2680 00003E22 88A3[9F6E0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2681                              <1> 		; clrb p.stat-1(r1) / free the process
  2682                              <1> 	;shl	bx, 1
  2683 00003E28 D0E3                <1> 	shl	bl, 1
  2684                              <1> 		; asl r1 / use r1 for index into the below tables
  2685 00003E2A 668B8B[0E6E0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2686                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2687 00003E31 668B93[2E6E0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2688                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2689                              <1> 	; xor 	bx, bx ; 0
  2690 00003E38 30DB                <1> 	xor	bl, bl ; 0
  2691                              <1> 		; clr r2
  2692 00003E3A 31F6                <1> 	xor	esi, esi ; 0
  2693                              <1> 		; clr r5 / initialize reg
  2694                              <1> sysexit_2: ; 1:
  2695                              <1> 	        ; / find children of this dying process, 
  2696                              <1> 		; / if they are zombies, free them
  2697                              <1> 	;add	bx, 2
  2698 00003E3C 80C302              <1> 	add	bl, 2
  2699                              <1> 		; add $2,r2 / search parent process table 
  2700                              <1> 		          ; / for dying process's name
  2701 00003E3F 66398B[2E6E0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2702                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2703 00003E46 7513                <1> 	jne	short sysexit_4
  2704                              <1> 		; bne 3f / no
  2705                              <1> 	;shr	bx, 1
  2706 00003E48 D0EB                <1> 	shr	bl, 1
  2707                              <1> 		; asr r2 / yes, it is a parent
  2708 00003E4A 80BB[9F6E0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2709                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2710                              <1> 				     ; / dying process a zombie
  2711 00003E51 7506                <1> 	jne	short sysexit_3 
  2712                              <1> 		; bne 2f / no
  2713 00003E53 88A3[9F6E0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2714                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2715                              <1> sysexit_3: ; 2:
  2716                              <1> 	;shr	bx, 1
  2717 00003E59 D0E3                <1> 	shl	bl, 1
  2718                              <1> 		; asl r2
  2719                              <1> sysexit_4: ; 3:
  2720                              <1> 		; / search the process name table 
  2721                              <1> 		; / for the dying process's parent
  2722 00003E5B 663993[0E6E0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2723                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2724 00003E62 7502                <1> 	jne	short sysexit_5
  2725                              <1> 		; bne 3f / no
  2726 00003E64 89DE                <1> 	mov	esi, ebx
  2727                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2728                              <1> 		          ; / process # x2) in r5
  2729                              <1> sysexit_5: ; 3:
  2730                              <1> 	;cmp	bx, nproc + nproc
  2731 00003E66 80FB20              <1> 	cmp	bl, nproc + nproc
  2732                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2733 00003E69 72D1                <1> 	jb	short sysexit_2
  2734                              <1> 		; blt 1b / no, go back
  2735                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2736 00003E6B 21F6                <1> 	and	esi, esi ; r5=r1
  2737 00003E6D 7431                <1> 	jz	short sysexit_6
  2738                              <1> 		; beq 2f / no parent has been found. 
  2739                              <1> 		       ; / The process just dies
  2740 00003E6F 66D1EE              <1> 	shr	si, 1
  2741                              <1> 		; asr r1 / set up index to p.stat
  2742 00003E72 8A86[9F6E0000]      <1> 	mov	al, [esi+p.stat-1]
  2743                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2744 00003E78 20C0                <1> 	and	al, al
  2745 00003E7A 7424                <1> 	jz	short sysexit_6
  2746                              <1> 		; beq 2f / if its been freed, 2f
  2747 00003E7C 3C03                <1> 	cmp	al, 3
  2748                              <1> 		; cmp r2,$3 / is parent a zombie?
  2749 00003E7E 7420                <1> 	je	short sysexit_6
  2750                              <1> 		; beq 2f / yes, 2f
  2751                              <1> 	; BH = 0
  2752 00003E80 8A1D[89710000]      <1> 	mov	bl, [u.uno]
  2753                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2754 00003E86 C683[9F6E0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2755                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2756                              <1> 	; 05/02/2014
  2757 00003E8D 3C01                <1> 	cmp	al, 1 ; SRUN
  2758 00003E8F 740F                <1> 	je	short sysexit_6
  2759                              <1> 	;cmp	al, 2
  2760                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2761                              <1> 			  ; / this child to die
  2762                              <1> 	;jne	short sysexit_6	
  2763                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2764                              <1> 	; 05/02/2014
  2765                              <1> 	; p.stat = 2 --> waiting
  2766                              <1> 	; p.stat = 4 --> sleeping
  2767 00003E91 C686[9F6E0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2768                              <1> 	;dec	byte [esi+p.stat-1]
  2769                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2770 00003E98 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2771                              <1> 	; 
  2772                              <1> 	;mov	ebx, runq + 4
  2773                              <1> 		; mov $runq+4,r2 / on the runq
  2774 00003E9B E8DD120000          <1> 	call	putlu
  2775                              <1> 		; jsr r0, putlu
  2776                              <1> sysexit_6: ; 2:
  2777                              <1> 	; 31/08/2015
  2778                              <1> 		; / the process dies
  2779 00003EA0 C605[89710000]00    <1> 	mov	byte [u.uno], 0
  2780                              <1> 		; clrb u.uno / put zero as the process number, 
  2781                              <1> 	           ; / so "swap" will
  2782 00003EA7 E804120000          <1> 	call	swap
  2783                              <1> 		; jsr r0,swap / overwrite process with another process
  2784                              <1> hlt_sys:
  2785                              <1> 	;sti ; 18/01/2014
  2786                              <1> hlts0:
  2787 00003EAC F4                  <1> 	hlt
  2788 00003EAD EBFD                <1> 	jmp	short hlts0
  2789                              <1> 		; 0 / and thereby kill it; halt?
  2790                              <1> 
  2791                              <1> 
  2792                              <1> syswait: ; < wait for a processs to die >
  2793                              <1> 	; 17/09/2015
  2794                              <1> 	; 02/09/2015
  2795                              <1> 	; 01/09/2015
  2796                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2797                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2798                              <1> 	;
  2799                              <1> 	; 'syswait' waits for a process die. 
  2800                              <1> 	; It works in following way:
  2801                              <1> 	;    1) From the parent process number, the parent's 
  2802                              <1> 	; 	process name is found. The p.ppid table of parent
  2803                              <1> 	;	names is then searched for this process name.
  2804                              <1> 	;	If a match occurs, r2 contains child's process
  2805                              <1> 	;	number. The child status is checked to see if it is
  2806                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2807                              <1> 	;	If it is, the child process is freed and it's name
  2808                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2809                              <1> 	;	If the child is not a zombie, nothing happens and
  2810                              <1> 	;	the search goes on through the p.ppid table until
  2811                              <1> 	;	all processes are checked or a zombie is found.
  2812                              <1> 	;    2) If no zombies are found, a check is made to see if
  2813                              <1> 	;	there are any children at all. If there are none,
  2814                              <1> 	;	an error return is made. If there are, the parent's
  2815                              <1> 	;	status is set to 2 (waiting for child to die),
  2816                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2817                              <1> 	;	is made to wait on the next process.
  2818                              <1> 	;
  2819                              <1> 	; Calling sequence:
  2820                              <1> 	;	?
  2821                              <1> 	; Arguments:
  2822                              <1> 	;	-
  2823                              <1> 	; Inputs: - 
  2824                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2825                              <1> 	; ...............................................................
  2826                              <1> 	;				
  2827                              <1> 	
  2828                              <1> ; / wait for a process to die
  2829                              <1> 
  2830                              <1> syswait_0:
  2831 00003EAF 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2832                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2833 00003EB6 D0E3                <1> 	shl	bl, 1
  2834                              <1> 	;shl	bx, 1
  2835                              <1> 		; asl r1 / x2 to get index into p.pid table
  2836 00003EB8 668B83[0E6E0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2837                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2838 00003EBF 31F6                <1> 	xor	esi, esi
  2839                              <1> 		; clr r2
  2840 00003EC1 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2841                              <1> 	;xor 	cl, cl
  2842                              <1> 		; clr r3 / initialize reg 3
  2843                              <1> syswait_1: ; 1:
  2844 00003EC3 6683C602            <1> 	add	si, 2
  2845                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2846                              <1> 			  ; / search table of parent processes 
  2847                              <1> 			  ; / for this process name
  2848 00003EC7 663B86[2E6E0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2849                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2850                              <1> 			            ; / process number
  2851 00003ECE 7535                <1> 	jne	short syswait_3
  2852                              <1> 		;bne 3f / branch if no match of parent process name
  2853                              <1> 	;inc	cx
  2854 00003ED0 FEC1                <1> 	inc	cl
  2855                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2856 00003ED2 66D1EE              <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 00003ED5 80BE[9F6E0000]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 00003EDC 7524                <1> 	jne	short syswait_2
  2866                              <1> 		; bne 2f / no, skip it
  2867 00003EDE 88BE[9F6E0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2868                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2869 00003EE4 66D1E6              <1> 	shl	si, 1
  2870                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2871 00003EE7 0FB786[0E6E0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2872 00003EEE A3[34710000]        <1> 	mov	[u.r0], eax
  2873                              <1> 		; mov p.pid-2(r2),*u.r0 
  2874                              <1> 			      ; / put childs process name in (u.r0)
  2875                              <1> 	;
  2876                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2877                              <1> 	;
  2878                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2879                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2880                              <1> 	; system call loop from the application/program if it calls
  2881                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2882                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2883                              <1> 	;
  2884                              <1> 	; Note: syswait will return with error if there is not a
  2885                              <1> 	;       zombie or running process to wait.	
  2886                              <1> 	;
  2887 00003EF3 6629C0              <1> 	sub	ax, ax
  2888 00003EF6 668986[2E6E0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2889 00003EFD E9E7FDFFFF          <1> 	jmp	sysret0 ; ax = 0
  2890                              <1> 	;
  2891                              <1> 	;jmp	sysret
  2892                              <1> 		; br sysret1 / return cause child is dead
  2893                              <1> syswait_2: ; 2:
  2894 00003F02 66D1E6              <1> 	shl	si, 1
  2895                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2896                              <1> syswait_3: ; 3:
  2897 00003F05 6683FE20            <1> 	cmp	si, nproc+nproc
  2898                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2899 00003F09 72B8                <1> 	jb	short syswait_1
  2900                              <1> 		; blt 1b / no, continue search
  2901                              <1> 	;and	cx, cx
  2902 00003F0B 20C9                <1> 	and	cl, cl
  2903                              <1> 		; tst r3 / one gets here if there are no children 
  2904                              <1> 		       ; / or children that are still active
  2905                              <1> 	; 30/10/2013
  2906 00003F0D 750B                <1> 	jnz	short syswait_4
  2907                              <1> 	;jz	error
  2908                              <1> 		; beq error1 / there are no children, error
  2909 00003F0F 890D[34710000]      <1> 	mov	[u.r0], ecx ; 0
  2910 00003F15 E9ADFDFFFF          <1> 	jmp	error
  2911                              <1> syswait_4:
  2912 00003F1A 8A1D[89710000]      <1> 	mov	bl, [u.uno]
  2913                              <1> 		; movb u.uno,r1 / there are children so put 
  2914                              <1> 			      ; / parent process number in r1
  2915 00003F20 FE83[9F6E0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2916                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2917                              <1> 				  ; / other children to die
  2918                              <1> 	; 04/11/2013
  2919 00003F26 E885110000          <1> 	call	swap
  2920                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2921 00003F2B EB82                <1> 	jmp	syswait_0
  2922                              <1> 		; br syswait / wait on next process
  2923                              <1> 
  2924                              <1> sysfork: ; < create a new process >
  2925                              <1> 	; 18/09/2015
  2926                              <1> 	; 04/09/2015
  2927                              <1> 	; 02/09/2015
  2928                              <1> 	; 01/09/2015
  2929                              <1> 	; 28/08/2015
  2930                              <1> 	; 14/05/2015
  2931                              <1> 	; 10/05/2015
  2932                              <1> 	; 09/05/2015
  2933                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2934                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2935                              <1> 	;
  2936                              <1> 	; 'sysfork' creates a new process. This process is referred
  2937                              <1> 	; to as the child process. This new process core image is
  2938                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  2939                              <1> 	; distinction is the return location and the fact that (u.r0)
  2940                              <1> 	; in the old process (parent) contains the process id (p.pid)
  2941                              <1> 	; of the new process (child). This id is used by 'syswait'.
  2942                              <1> 	; 'sysfork' works in the following manner: 	
  2943                              <1> 	;    1) The process status table (p.stat) is searched to find
  2944                              <1> 	;	a process number that is unused. If none are found
  2945                              <1> 	;	an error occurs.
  2946                              <1> 	;    2) when one is found, it becomes the child process number
  2947                              <1> 	;	and it's status (p.stat) is set to active.
  2948                              <1> 	;    3) If the parent had a control tty, the interrupt 
  2949                              <1> 	;	character in that tty buffer is cleared.
  2950                              <1> 	;    4) The child process is put on the lowest priority run 
  2951                              <1> 	;	queue via 'putlu'.
  2952                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  2953                              <1> 	;	it is a unique number) and is put in the child's unique
  2954                              <1> 	;	identifier; process id (p.pid).
  2955                              <1> 	;    6) The process name of the parent is then obtained and
  2956                              <1> 	;	placed in the unique identifier of the parent process
  2957                              <1> 	;	name is then put in 'u.r0'.	
  2958                              <1> 	;    7) The child process is then written out on disk by
  2959                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  2960                              <1> 	;	and the child is born. (The child process is written 
  2961                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  2962                              <1> 	;	number.)
  2963                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  2964                              <1> 	;    9) The child process name is put in 'u.r0'.
  2965                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  2966                              <1> 	;	create the return address for the parent process.
  2967                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  2968                              <1> 	;	the parent has opened. For each file the parent has
  2969                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  2970                              <1> 	;	to indicate that the child process also has opened
  2971                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  2972                              <1> 	;
  2973                              <1> 	; Calling sequence:
  2974                              <1> 	;	from shell ?
  2975                              <1> 	; Arguments:
  2976                              <1> 	;	-
  2977                              <1> 	; Inputs: -
  2978                              <1> 	; Outputs: *u.r0 - child process name
  2979                              <1> 	; ...............................................................
  2980                              <1> 	;	
  2981                              <1> 	; Retro UNIX 8086 v1 modification: 
  2982                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  2983                              <1> 	;	= process id of child a parent process returns
  2984                              <1> 	;	= process id of parent when a child process returns
  2985                              <1> 	;
  2986                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  2987                              <1> 	;	in following manner: (with an example: c library, fork)
  2988                              <1> 	;	
  2989                              <1> 	;	1:
  2990                              <1> 	;		sys	fork
  2991                              <1> 	;			br 1f  / child process returns here
  2992                              <1> 	;		bes	2f     / parent process returns here
  2993                              <1> 	;		/ pid of new process in r0
  2994                              <1> 	;		rts	pc
  2995                              <1> 	;	2: / parent process condionally branches here
  2996                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  2997                              <1> 	;		rts	pc
  2998                              <1> 	;
  2999                              <1> 	;	1: / child process brances here
  3000                              <1> 	;		clr	r0   / pid = 0 in child process
  3001                              <1> 	;		rts	pc
  3002                              <1> 	;
  3003                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3004                              <1> 	;		// pid = fork();
  3005                              <1> 	;		//
  3006                              <1> 	;		// pid == 0 in child process; 
  3007                              <1> 	;		// pid == -1 means error return
  3008                              <1> 	;		// in child, 
  3009                              <1> 	;		//	parents id is in par_uid if needed
  3010                              <1> 	;		
  3011                              <1> 	;		_fork:
  3012                              <1> 	;			mov	$.fork,eax
  3013                              <1> 	;			int	$0x30
  3014                              <1> 	;			jmp	1f
  3015                              <1> 	;			jnc	2f
  3016                              <1> 	;			jmp	cerror
  3017                              <1> 	;		1:
  3018                              <1> 	;			mov	eax,_par_uid
  3019                              <1> 	;			xor	eax,eax
  3020                              <1> 	;		2:
  3021                              <1> 	;			ret
  3022                              <1> 	;
  3023                              <1> 	;	In Retro UNIX 8086 v1,
  3024                              <1> 	;	'sysfork' returns in following manner:
  3025                              <1> 	;	
  3026                              <1> 	;		mov	ax, sys_fork
  3027                              <1> 	;		mov	bx, offset @f ; routine for child
  3028                              <1> 	;		int	20h
  3029                              <1> 	;		jc	error
  3030                              <1> 	;		
  3031                              <1> 	;	; Routine for parent process here (just after 'jc')
  3032                              <1> 	;		mov	word ptr [pid_of_child], ax
  3033                              <1> 	;		jmp	next_routine_for_parent	
  3034                              <1> 	;
  3035                              <1> 	;	@@: ; routine for child process here				
  3036                              <1> 	;		....	
  3037                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3038                              <1> 	;	       for child process by using BX input.
  3039                              <1> 	;	      (at first, parent process will return then 
  3040                              <1> 	;	      child process will return -after swapped in-
  3041                              <1> 	;	      'syswait' is needed in parent process
  3042                              <1> 	;	      if return from child process will be waited for.)
  3043                              <1> 	;	  				
  3044                              <1> 	
  3045                              <1> ; / create a new process
  3046                              <1> 	; EBX = return address for child process 
  3047                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3048 00003F2D 31F6                <1> 	xor 	esi, esi
  3049                              <1> 		; clr r1
  3050                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3051 00003F2F 46                  <1> 	inc	esi
  3052                              <1> 		; inc r1
  3053 00003F30 80BE[9F6E0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3054                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3055 00003F37 760B                <1> 	jna	short sysfork_2	
  3056                              <1> 		; beq 1f / it's unused so branch
  3057 00003F39 6683FE10            <1> 	cmp	si, nproc
  3058                              <1> 		; cmp r1,$nproc / all processes checked
  3059 00003F3D 72F0                <1> 	jb	short sysfork_1
  3060                              <1> 		; blt 1b / no, branch back
  3061                              <1> 	;
  3062                              <1> 	; Retro UNIX 8086 v1. modification:
  3063                              <1> 	;	Parent process returns from 'sysfork' to address 
  3064                              <1> 	;	which is just after 'sysfork' system call in parent
  3065                              <1> 	;	process. Child process returns to address which is put
  3066                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3067                              <1> 	;
  3068                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3069                              <1> 		             ; / to old process return
  3070                              <1> 		; br error1 / no room for a new process
  3071 00003F3F E983FDFFFF          <1> 	jmp	error
  3072                              <1> sysfork_2: ; 1:
  3073 00003F44 E827F0FFFF          <1> 	call	allocate_page
  3074 00003F49 0F8278FDFFFF        <1> 	jc	error
  3075 00003F4F 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3076                              <1> 	; Retro UNIX 386 v1 modification!
  3077 00003F50 E814F2FFFF          <1> 	call	duplicate_page_dir
  3078                              <1> 		; EAX = New page directory 
  3079 00003F55 730B                <1> 	jnc	short sysfork_3
  3080 00003F57 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3081 00003F58 E8DBF1FFFF          <1> 	call 	deallocate_page
  3082 00003F5D E965FDFFFF          <1> 	jmp	error
  3083                              <1> sysfork_3:
  3084                              <1> 	; Retro UNIX 386 v1 modification !
  3085 00003F62 56                  <1> 	push	esi
  3086 00003F63 E8BF110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3087                              <1> 		      ; and interrupt return components (for IRET)
  3088 00003F68 8705[98710000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3089 00003F6E A3[9C710000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3090 00003F73 5E                  <1> 	pop	esi
  3091 00003F74 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3092                              <1> 		; [u.usp] = esp
  3093 00003F75 89F7                <1> 	mov	edi, esi
  3094 00003F77 66C1E702            <1> 	shl	di, 2
  3095 00003F7B 8987[AC6E0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3096 00003F81 A3[94710000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3097                              <1> 	; 28/08/2015
  3098 00003F86 0FB605[89710000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3099                              <1> 		; movb u.uno,-(sp) / save parent process number
  3100 00003F8D 89C7                <1> 	mov	edi, eax
  3101 00003F8F 50                  <1>         push	eax ; ** 
  3102 00003F90 8A87[6F6E0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3103                              <1> 	; 18/09/2015
  3104                              <1> 	;mov	[esi+p.ttyc-1], al ; set child's console tty
  3105                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3106 00003F96 668986[6F6E0000]    <1> 	mov     [esi+p.ttyc-1], ax ; al - set child's console tty
  3107                              <1> 				   ; ah - reset child's wait channel	
  3108 00003F9D 89F0                <1> 	mov	eax, esi
  3109 00003F9F A2[89710000]        <1> 	mov	[u.uno], al ; child process number
  3110                              <1> 		;movb r1,u.uno / set child process number to r1
  3111 00003FA4 FE86[9F6E0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3112                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3113                              <1> 				; / process to active status
  3114                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3115                              <1> 			      ; / control tty buffer in r2
  3116                              <1>                 ; beq 2f / branch, if no such tty assigned
  3117                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3118                              <1> 	; 2:
  3119 00003FAA 53                  <1> 	push	ebx  ; * return address for the child process
  3120                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3121                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3122                              <1> 		; mov $runq+4,r2
  3123 00003FAB E8CD110000          <1> 	call	putlu 
  3124                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3125                              <1> 			   ; / run queue
  3126 00003FB0 66D1E6              <1> 	shl	si, 1
  3127                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3128                              <1> 		       ; / into p.pid table
  3129 00003FB3 66FF05[1A710000]    <1> 	inc	word [mpid]
  3130                              <1> 		; inc mpid / increment m.pid; get a new process name
  3131 00003FBA 66A1[1A710000]      <1> 	mov	ax, [mpid]
  3132 00003FC0 668986[0E6E0000]    <1> 	mov	[esi+p.pid-2], ax
  3133                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3134                              <1> 				    ; / in child process' name slot
  3135 00003FC7 5A                  <1> 	pop	edx  ; * return address for the child process
  3136                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3137 00003FC8 5B                  <1>   	pop	ebx  ; **
  3138                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3139                              <1> 		; movb (sp),r2 / put parent process number in r2
  3140 00003FC9 66D1E3              <1> 	shl 	bx, 1
  3141                              <1> 		;asl r2 / multiply by 2 to get index into below tables
  3142                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3143 00003FCC 668B83[0E6E0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3144                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3145                              <1> 				   ; / process
  3146 00003FD3 668986[2E6E0000]    <1> 	mov	[esi+p.ppid-2], ax
  3147                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3148                              <1> 			  ; / in parent process slot for child
  3149 00003FDA A3[34710000]        <1> 	mov	[u.r0], eax	
  3150                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3151                              <1> 			     ; / at location where r0 was saved
  3152 00003FDF 8B2D[2C710000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3153 00003FE5 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3154                              <1> 			   ; * return address for the child process
  3155                              <1> 		; mov $sysret1,-(sp) /
  3156                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3157                              <1> 			      ; / user is swapped out
  3158                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3159                              <1> 	; 04/09/2015 - 01/09/2015
  3160                              <1> 	; [u.usp] = esp
  3161 00003FE8 68[E73C0000]        <1> 	push	sysret ; ***
  3162 00003FED 8925[30710000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3163                              <1> 			     ; (for child process)	
  3164 00003FF3 31C0                <1> 	xor 	eax, eax
  3165 00003FF5 66A3[6E710000]      <1> 	mov 	[u.ttyp], ax ; 0
  3166                              <1> 	;
  3167 00003FFB E827110000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3168                              <1> 		;jsr r0,wswap / put child process out on drum
  3169                              <1> 		;jsr r0,unpack / unpack user stack
  3170                              <1> 		;mov u.usp,sp / restore user stack pointer
  3171                              <1> 		; tst (sp)+ / bump stack pointer
  3172                              <1> 	; Retro UNIX 386 v1 modification !
  3173 00004000 58                  <1> 	pop	eax ; ***
  3174 00004001 66D1E3              <1> 	shl	bx, 1
  3175 00004004 8B83[AC6E0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3176 0000400A E841110000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3177                              <1> 		      ; registers and return address (for IRET)
  3178                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3179 0000400F 0FB705[1A710000]    <1>         movzx   eax, word [mpid]
  3180 00004016 A3[34710000]        <1> 	mov	[u.r0], eax
  3181                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3182                              <1> 			       ; / where r0 was saved
  3183                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3184                              <1> 			          ; / process return
  3185                              <1> 	;xor	ebx, ebx
  3186 0000401B 31F6                <1> 	xor     esi, esi
  3187                              <1> 		;clr r1
  3188                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3189                              <1> 	      ; / opened by the parent process
  3190                              <1> 	; 01/09/2015
  3191                              <1> 	;xor	bh, bh
  3192                              <1> 	;mov 	bl, [esi+u.fp]
  3193 0000401D 8A86[3E710000]      <1> 	mov 	al, [esi+u.fp]
  3194                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3195                              <1>         ;or	bl, bl
  3196 00004023 08C0                <1> 	or	al, al
  3197 00004025 740B                <1> 	jz	short sysfork_5	
  3198                              <1> 		; beq 2f / file has not been opened by parent, 
  3199                              <1> 		       ; / so branch
  3200                              <1> 	;mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3201 00004027 F6E4                <1> 	mul	ah
  3202                              <1> 	;movzx	ebx, ax
  3203 00004029 6689C3              <1> 	mov	bx, ax
  3204                              <1> 	;shl	bx, 3
  3205                              <1> 		; asl r2 / multiply by 8
  3206                              <1>        		; asl r2 / to get index into fsp table
  3207                              <1>        		; asl r2
  3208 0000402C FE83[CE6D0000]      <1>   	inc     byte [ebx+fsp-2]
  3209                              <1> 		; incb fsp-2(r2) / increment number of processes
  3210                              <1> 			     ; / using file, because child will now be
  3211                              <1> 			     ; / using this file
  3212                              <1> sysfork_5: ; 2:
  3213 00004032 46                  <1>         inc     esi
  3214                              <1> 		; inc r1 / get next open file
  3215 00004033 6683FE0A            <1>         cmp     si, 10
  3216                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3217                              <1> 			  ; / can be opened
  3218 00004037 72E4                <1> 	jb	short sysfork_4	
  3219                              <1> 		; blt 1b / check next entry
  3220 00004039 E9A9FCFFFF          <1> 	jmp	sysret
  3221                              <1> 		; br sysret1
  3222                              <1> 
  3223                              <1> sysread: ; < read from file >
  3224                              <1> 	; 24/12/2021
  3225                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3226                              <1> 	; 27/03/2020
  3227                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3228                              <1> 	; 13/05/2015
  3229                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3230                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3231                              <1> 	;
  3232                              <1> 	; 'sysread' is given a buffer to read into and the number of
  3233                              <1> 	; characters to be read. If finds the file from the file
  3234                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3235                              <1> 	; is returned from a successful open call (sysopen).
  3236                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3237                              <1> 	; is read into core via 'readi'.
  3238                              <1> 	;
  3239                              <1> 	; Calling sequence:
  3240                              <1> 	;	sysread; buffer; nchars
  3241                              <1> 	; Arguments:
  3242                              <1> 	;	buffer - location of contiguous bytes where 
  3243                              <1> 	;		 input will be placed.
  3244                              <1> 	;	nchars - number of bytes or characters to be read.
  3245                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3246                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3247                              <1> 	; ...............................................................
  3248                              <1> 	;				
  3249                              <1> 	; Retro UNIX 8086 v1 modification: 
  3250                              <1> 	;       'sysread' system call has three arguments; so,
  3251                              <1> 	;	* 1st argument, file descriptor is in BX register
  3252                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3253                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3254                              <1> 	;
  3255                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3256                              <1> 	;	to the user with number of bytes read. 
  3257                              <1> 	;
  3258                              <1> 
  3259                              <1> ; temporary ! - 26/12/2021
  3260 0000403E C605[96400000]52    <1> mov byte [srwtype], 'R'
  3261                              <1> 
  3262 00004045 E859000000          <1> 	call	rw1
  3263                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3264                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3265                              <1>        	; 04/12/2021
  3266 0000404A 7221                <1> 	jc	short sysread_err
  3267 0000404C 7549                <1> 	jnz	short rw3 ; error ! (permission denied)
  3268                              <1> 	;		; read a file while it is open for write!
  3269                              <1> 
  3270                              <1> 	; eax = inode number
  3271                              <1> 
  3272                              <1> 	; 04/12/2021
  3273                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3274                              <1> 	;test	ah, 80h
  3275                              <1> 	;	; tst r1 / negative i-number?
  3276                              <1> 	;;jnz	error
  3277                              <1> 	;;	; ble error1 / yes, error 1 to read
  3278                              <1> 	;;		   ; / it should be positive
  3279                              <1> 	;; 04/12/2021
  3280                              <1> 	;jnz	short sysread_err
  3281                              <1> 
  3282                              <1> ; temporary - 26/12/2021
  3283 0000404E 53                  <1> push	ebx
  3284 0000404F 50                  <1> push	eax
  3285 00004050 B058                <1> mov	al, 'X'
  3286 00004052 B44E                <1> mov	ah, 4Eh	
  3287 00004054 8B1D[1F420000]      <1> mov	ebx, [openaddr]
  3288 0000405A 8005[1F420000]02    <1> add	byte [openaddr], 2
  3289 00004061 668903              <1> mov	word [ebx], ax
  3290 00004064 58                  <1> pop	eax
  3291 00004065 5B                  <1> pop	ebx
  3292                              <1> 
  3293 00004066 E8E5170000          <1> 	call	readi
  3294                              <1> 		; jsr r0,readi / read data into core
  3295 0000406B EB1A                <1> 	jmp	short rw0
  3296                              <1> 		; br 1f
  3297                              <1> sysread_err:
  3298                              <1> syswrite_err:
  3299                              <1> 	; 04/12/2021
  3300 0000406D E955FCFFFF          <1> 	jmp	error
  3301                              <1> 
  3302                              <1> syswrite: ; < write to file >
  3303                              <1> 	; 24/12/2021
  3304                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3305                              <1> 	; 27/03/2020
  3306                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3307                              <1> 	; 13/05/2015
  3308                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3309                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3310                              <1> 	;
  3311                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3312                              <1> 	; and the number of characters to write. If finds the file
  3313                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3314                              <1> 	; descriptor is returned from a successful open or create call
  3315                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3316                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3317                              <1> 	;
  3318                              <1> 	; Calling sequence:
  3319                              <1> 	;	syswrite; buffer; nchars
  3320                              <1> 	; Arguments:
  3321                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3322                              <1> 	;	nchars - number of characters to be written.
  3323                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3324                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3325                              <1> 	; ...............................................................
  3326                              <1> 	;				
  3327                              <1> 	; Retro UNIX 8086 v1 modification: 
  3328                              <1> 	;       'syswrite' system call has three arguments; so,
  3329                              <1> 	;	* 1st argument, file descriptor is in BX register
  3330                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3331                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3332                              <1> 	;
  3333                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3334                              <1> 	;	to the user with number of bytes written. 
  3335                              <1> 	;
  3336                              <1> 
  3337                              <1> ; temporary ! - 26/12/2021
  3338 00004072 C605[96400000]56    <1> mov byte [srwtype], 'V'
  3339                              <1> 
  3340 00004079 E825000000          <1> 	call	rw1
  3341                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3342                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3343                              <1>        	; 04/12/2021
  3344 0000407E 72ED                <1> 	jc	short syswrite_err
  3345 00004080 7415                <1> 	jz	short rw3 ; error ! (permission denied)
  3346                              <1> 			; write to a file while it is open for read
  3347                              <1> 	; eax = inode number
  3348                              <1> 	
  3349                              <1> 	; 04/12/2021
  3350                              <1> 	;((Retro Unix 386 v1 code)) (old code below)
  3351                              <1> 	;test	ah, 80h
  3352                              <1> 	;	; tst r1 / positive i-number ?
  3353                              <1>         ;jz	short rw3 ; 13/05/2015
  3354                              <1> 	;;jz	error
  3355                              <1> 	;	; bge error1 / yes, error 1 
  3356                              <1> 	;		   ; / negative i-number means write
  3357                              <1>         ;neg	ax
  3358                              <1> 	;	; neg r1 / make it positive
  3359                              <1> 	
  3360 00004082 E8DA190000          <1> 	call	writei
  3361                              <1>         	; jsr r0,writei / write data
  3362                              <1> rw0: ; 1:
  3363 00004087 A1[64710000]        <1>         mov	eax, [u.nread]
  3364 0000408C A3[34710000]        <1> 	mov	[u.r0], eax
  3365                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3366                              <1> 				  ; / into (u.r0)
  3367 00004091 E951FCFFFF          <1> 	jmp	sysret
  3368                              <1>         	; br sysret1
  3369                              <1> 
  3370                              <1> ; temporary - 26/12/2021
  3371 00004096 00                  <1> srwtype: db 0
  3372                              <1> 
  3373                              <1> rw3: 
  3374                              <1> ; temporary - 26/12/2021
  3375                              <1> ;mov dword [0B8000h], 4E354E35h
  3376                              <1> ;mov ecx, 0FFFFh
  3377                              <1> ;aboveysx:
  3378                              <1> ;dec edx
  3379                              <1> ;inc edx
  3380                              <1> ;loop aboveysx
  3381                              <1> ;stc
  3382                              <1> ;rw4:
  3383                              <1> 	; 13/05/2015
  3384 00004097 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3384 0000409F 0000                <1>
  3385                              <1> 	;stc
  3386                              <1> 	;retn
  3387                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.2
  3388 000040A1 EBCA                <1> 	jmp	short syswrite_err
  3389                              <1> 
  3390                              <1> rw1:	
  3391                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3392                              <1> 	; 27/03/2020
  3393                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3394                              <1> 	; 14/05/2015
  3395                              <1> 	; 13/05/2015
  3396                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3397                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3398                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3399                              <1> 	;
  3400                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3401                              <1> 				;(in the user's virtual memory space)
  3402                              <1> 	;mov	[u.count], edx 
  3403                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3404                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3405                              <1> 	;;mov	eax, ebx ; file descriptor
  3406                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3407                              <1> 		             ; / (index to u.fp table) in r1
  3408                              <1> 	; 13/05/2015
  3409 000040A3 C705[34710000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3409 000040AB 0000                <1>
  3410                              <1> 	;
  3411                              <1> 	;; call	getf
  3412                              <1>         ; ebx = File descriptor
  3413 000040AD E8370B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3414                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3415                              <1> 	; AX = I-number of the file ; negative i-number means write
  3416                              <1> 
  3417                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3418                              <1> 	; 26/03/2020 - Retro UNIX 386 v2
  3419                              <1> 	; BL = open mode & status flag (0 = read, 1 = write)
  3420                              <1> 	; eax = inode number (ax)
  3421                              <1> 	; 27/03/2020
  3422                              <1> 	; [cdev] = logical drive number 	
  3423                              <1> 
  3424                              <1> 	; 13/05/2015
  3425 000040B2 6683F801            <1> 	cmp 	ax, 1
  3426 000040B6 7237                <1> 	jb	short rw2
  3427                              <1> 	;
  3428 000040B8 890D[5C710000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3429                              <1> 				;(in the user's virtual memory space)
  3430 000040BE 8915[60710000]      <1> 	mov	[u.count], edx 
  3431                              <1> 	; 14/05/2015
  3432 000040C4 C705[AC710000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3432 000040CC 0000                <1>
  3433                              <1> 
  3434                              <1> 
  3435                              <1> ; temporary - 27/12/2021
  3436 000040CE 08DB                <1> or	bl, bl
  3437 000040D0 7519                <1> jnz	short ghi
  3438 000040D2 50                  <1> push	eax
  3439 000040D3 B44E                <1> mov	ah, 4Eh
  3440 000040D5 B052                <1> mov	al, 'R'
  3441 000040D7 66A304800B00        <1> mov	word [0B8004h], ax
  3442 000040DD A0[23420000]        <1> mov	al, [bytype]
  3443 000040E2 0430                <1> add	al, '0'
  3444 000040E4 66A306800B00        <1> mov	word [0B8006h], ax
  3445 000040EA 58                  <1> pop	eax
  3446                              <1> ghi:
  3447                              <1> 
  3448                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3449                              <1> 	; 27/03/2020 - Retro UNIX 386 v2
  3450 000040EB 80E301              <1> 	and	bl, 1
  3451                              <1> 		; zf = 0 -> open for write	
  3452                              <1> 		; zf = 1 -> open for read
  3453                              <1> 	;
  3454 000040EE C3                  <1> 	retn
  3455                              <1>         	; rts r0
  3456                              <1> rw2:
  3457                              <1> ; temporary - 25/12/2021
  3458 000040EF C70500800B00344E34- <1> mov dword [0B8000h], 4E344E34h
  3458 000040F8 4E                  <1>
  3459 000040F9 B9FFFF0000          <1> mov ecx, 0FFFFh
  3460                              <1> abovexsx:
  3461 000040FE 4A                  <1> dec edx
  3462 000040FF 42                  <1> inc edx
  3463 00004100 E2FC                <1> loop abovexsx
  3464 00004102 F9                  <1> stc
  3465                              <1> 	; 13/05/2015
  3466 00004103 C705[AC710000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3466 0000410B 0000                <1>
  3467 0000410D C3                  <1> 	retn
  3468                              <1> 
  3469                              <1> 	; 27/12/2021
  3470                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility code
  3471                              <1> sysopen: ;<open file>
  3472                              <1> 	; 04/12/2021
  3473                              <1> 	; 07/08/2020 (Retro UNIX 386 v2)
  3474                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3475                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3476                              <1> 	;
  3477                              <1> 	; 'sysopen' opens a file in following manner:
  3478                              <1> 	;    1) The second argument in a sysopen says whether to
  3479                              <1> 	;	open the file ro read (0) or write (>0).
  3480                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3481                              <1> 	;    3) The file is opened by 'iopen'.
  3482                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3483                              <1> 	;	and the user's open file list - u.fp.
  3484                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3485                              <1> 	;	b) An entry for the file is created in the fsp table.
  3486                              <1> 	;	c) The number of this entry is put on u.fp list.
  3487                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3488                              <1> 	;	   to by u.r0.
  3489                              <1> 	;
  3490                              <1> 	; Calling sequence:
  3491                              <1> 	;	sysopen; name; mode
  3492                              <1> 	; Arguments:
  3493                              <1> 	;	name - file name or path name
  3494                              <1> 	;	mode - 0 to open for reading
  3495                              <1> 	;	       1 to open for writing
  3496                              <1> 	; Inputs: (arguments)
  3497                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3498                              <1> 	;		  is put into r0's location on the stack.	
  3499                              <1> 	; ...............................................................
  3500                              <1> 	;				
  3501                              <1> 	; Retro UNIX 8086 v1 modification: 
  3502                              <1> 	;       'sysopen' system call has two arguments; so,
  3503                              <1> 	;	* 1st argument, name is pointed to by BX register
  3504                              <1> 	;	* 2nd argument, mode is in CX register
  3505                              <1> 	;
  3506                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3507                              <1> 	;	to the user with the file descriptor/number 
  3508                              <1> 	;	(index to u.fp list).
  3509                              <1> 	;
  3510                              <1> 	;call	arg2
  3511                              <1> 	; * name - 'u.namep' points to address of file/path name
  3512                              <1> 	;          in the user's program segment ('u.segmnt')
  3513                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3514                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3515                              <1> 	;          which is on top of stack.
  3516                              <1> 	;
  3517                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3518                              <1> 	;
  3519                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3520                              <1> 
  3521 0000410E 891D[50710000]      <1> 	mov	[u.namep], ebx
  3522 00004114 51                  <1> 	push	ecx ; * ; 04/12/2021 (cx -> ecx)
  3523 00004115 E83A0B0000          <1> 	call	namei
  3524                              <1> 		; jsr r0,namei / i-number of file in r1
  3525                              <1>      	;and	ax, ax
  3526                              <1> 	;jz	error ; File not found
  3527 0000411A 722B                <1> 	jc	short fnotfound ; 14/05/2015
  3528                              <1> 	;jc	error ; 27/05/2013
  3529                              <1> 		; br  error2 / file not found
  3530                              <1>    	;pop	edx ; * ; mode ; 04/12/2021
  3531                              <1> 	;push	edx ; *
  3532                              <1> 	;;or	dx, dx
  3533                              <1> 	;or	dl, dl
  3534                              <1> 	;	; tst (sp) / is mode = 0 (2nd arg of call;
  3535                              <1> 	;	         ; / 0 means, open for read)
  3536                              <1> 	;;jz	short sysopen_0
  3537                              <1> 	;;	; beq 1f / yes, leave i-number positive
  3538                              <1> 	
  3539 0000411C 8B1424              <1> 	mov	edx, [esp] ; *
  3540                              <1> 	; edx = open mode (0 or 1)
  3541                              <1> 
  3542                              <1> ;syscreat_0: ;op0: ; 27/12/2015
  3543                              <1> ;	neg	ax
  3544                              <1> ;        	; neg r1 / open for writing so make i-number negative
  3545                              <1> 
  3546                              <1> sysopen_0: ;1:
  3547 0000411F E8081D0000          <1> 	call	iopen
  3548                              <1> 		; jsr r0,iopen / open file whose i-number is in r1
  3549 00004124 5A                  <1> 	pop	edx ; * ; mode ; 04/12/2021
  3550                              <1> 	;;and	dx, dx
  3551                              <1> 	;and	dl, dl
  3552                              <1>         ;	; tst (sp)+ / pop the stack and test the mode
  3553                              <1> 	;jz	short sysopen_2
  3554                              <1>         ;	; beq op1 / is open for read op1
  3555                              <1> ;sysopen_1: ;op0:
  3556                              <1> 	;neg	ax
  3557                              <1>         ;	; neg r1 
  3558                              <1> 	;	     ;/ make i-number positive if open for writing [???]
  3559                              <1> 
  3560                              <1> 	;; NOTE: iopen always make i-number positive.
  3561                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3562                              <1> sysopen_1: ; 04/12/2021
  3563                              <1> sysopen_2: ;op1:
  3564 00004125 31F6                <1>         xor     esi, esi
  3565                              <1>         	; clr r2 / clear registers
  3566 00004127 31DB                <1>         xor     ebx, ebx
  3567                              <1> 		; clr r3
  3568                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3569 00004129 389E[3E710000]      <1>         cmp     [esi+u.fp], bl ; 0
  3570                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3571 0000412F 7625                <1> 	jna	short sysopen_4_temp ; temporary - 26/12/2021 
  3572                              <1> 	;jna	short sysopen_4
  3573                              <1> 		; beq 1f / if byte in list is 0 branch
  3574 00004131 46                  <1>         inc     esi
  3575                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3576 00004132 6683FE0A            <1> 	cmp	si, OPENFILES ; 04/12/2021
  3577                              <1> 	;cmp	si, 10
  3578                              <1> 		; cmp r2,$10. / reached end of list?
  3579 00004136 72F1                <1> 	jb	short sysopen_3
  3580                              <1> 		; blt 1b / no, go back
  3581                              <1> toomanyf:
  3582                              <1> 	; 14/05/2015
  3583 00004138 C705[AC710000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3583 00004140 0000                <1>
  3584 00004142 E980FBFFFF          <1> 	jmp	error
  3585                              <1>         	; br error2 / yes, error (no files open)
  3586                              <1> fnotfound: 
  3587                              <1> 	; 14/05/2015
  3588 00004147 C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3588 0000414F 0000                <1>
  3589 00004151 E971FBFFFF          <1> 	jmp	error
  3590                              <1> 
  3591                              <1> ; temporary - 26/12/2021
  3592                              <1> sysopen_4_temp:
  3593 00004156 89F3                <1> 	mov	ebx, esi 
  3594 00004158 881D[23420000]      <1> 	mov	[bytype], bl
  3595 0000415E 31DB                <1> 	xor	ebx, ebx
  3596                              <1> 
  3597                              <1> sysopen_4: ; 1:
  3598 00004160 6683BB[D06D0000]00  <1>         cmp     word [ebx+fsp], 0
  3599                              <1> 		; tst fsp(r3) / scan fsp entries
  3600 00004168 7624                <1>         jna     short sysopen_5
  3601                              <1> 		; beq 1f / if 0 branch
  3602                              <1> 	;; 14/05/2015 - Retro UNIX 386 v1 modification !
  3603                              <1> 	;add	bx, 10 ; fsp structure size = 10 bytes/entry
  3604                              <1> 		; add $8.,r3 / add 8 to r3 
  3605                              <1> 			; / to bump it to next entry mfsp table
  3606                              <1> 	; 07/08/2020 - Retro UNIX 386 v2
  3607                              <1> 	;add	bx, 16 ; fsp structure size = 16 bytes/entry ; runix v2
  3608                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  3609 0000416A 6683C310            <1> 	add	bx, fp.size
  3610                              <1> 
  3611                              <1> ; temporary - 27/12/2021
  3612 0000416E 50                  <1> push	eax
  3613 0000416F B44E                <1> mov	ah, 4Eh
  3614 00004171 B021                <1> mov	al, '!'
  3615 00004173 66A304800B00        <1> mov	word [0B8004h], ax
  3616 00004179 51                  <1> push	ecx
  3617 0000417A B9FFFF0F00          <1> mov	ecx, 0FFFFFh
  3618                              <1> gcl:
  3619 0000417F 48                  <1> dec	eax
  3620 00004180 40                  <1> inc	eax
  3621 00004181 E2FC                <1> loop gcl
  3622 00004183 59                  <1> pop	ecx
  3623 00004184 58                  <1> pop	eax
  3624                              <1> 
  3625                              <1> 	; 22/11/2021
  3626 00004185 6681FB2003          <1> 	cmp	bx, NFILES*fp.size ; NFILES*16
  3627                              <1> 	;cmp	bx, nfiles*10
  3628                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3629 0000418A 72D4                <1> 	jb	short sysopen_4
  3630                              <1>        		; blt 1b / no, back
  3631                              <1> 	;jmp	error
  3632                              <1>         ;	; br error2 / yes, error
  3633                              <1> 	; 04/12/2021
  3634                              <1> 	; 07/08/2020
  3635 0000418C EBAA                <1> 	jmp	short toomanyf
  3636                              <1> 
  3637                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3638 0000418E 668983[D06D0000]    <1>         mov     [ebx+fsp], ax
  3639                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3640                              <1> 			; / into next available entry in fsp table,
  3641                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3642                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3643                              <1> 	;	; mov cdev,fsp+2(r3) / put # of device in next word
  3644                              <1> 
  3645                              <1> ; temporary - 27/12/2021
  3646 00004195 53                  <1> push	ebx
  3647 00004196 88D0                <1> mov	al, dl
  3648 00004198 0430                <1> add	al, '0'
  3649 0000419A 8B1D[1F420000]      <1> mov	ebx, [openaddr]
  3650 000041A0 8005[1F420000]02    <1> add	byte [openaddr], 2
  3651 000041A7 B44E                <1> mov	ah, 4Eh
  3652 000041A9 668903              <1> mov	word [ebx], ax
  3653 000041AC 8B1D[1F420000]      <1> mov	ebx, [openaddr]
  3654 000041B2 8005[1F420000]02    <1> add	byte [openaddr], 2
  3655 000041B9 A0[23420000]        <1> mov	al, [bytype]
  3656 000041BE 0441                <1> add	al, 'A'	
  3657 000041C0 668903              <1> mov	word [ebx], ax
  3658 000041C3 20D2                <1> and	dl, dl
  3659 000041C5 7524                <1> jnz	short fgh
  3660 000041C7 8B1C24              <1> mov	ebx, [esp]
  3661 000041CA C1EB04              <1> shr	ebx, 4
  3662 000041CD 80C330              <1> add	bl, '0'
  3663 000041D0 B052                <1> mov	al, 'R'
  3664 000041D2 66A300800B00        <1> mov	word [0B8000h], ax
  3665 000041D8 88D8                <1> mov	al, bl
  3666 000041DA 66A302800B00        <1> mov	word [0B8002h], ax
  3667 000041E0 51                  <1> push	ecx
  3668 000041E1 B9FFFF0F00          <1> mov	ecx, 0FFFFFh
  3669                              <1> gjl:
  3670 000041E6 48                  <1> dec	eax
  3671 000041E7 40                  <1> inc	eax
  3672 000041E8 E2FC                <1> loop gjl
  3673 000041EA 59                  <1> pop	ecx
  3674                              <1> fgh:
  3675 000041EB 5B                  <1> pop	ebx
  3676                              <1> 
  3677                              <1> 	; 04/12/2021        
  3678 000041EC A0[15710000]        <1> 	mov	al, [cdev]
  3679 000041F1 88D4                <1> 	mov	ah, dl ; open mode, 0 = read, 1 = write
  3680 000041F3 668983[D46D0000]    <1> 	mov	[ebx+fsp+4], ax ; device number & open mode
  3681                              <1> 
  3682                              <1> 	;xor	edi, edi
  3683                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3684                              <1> 	;	; clr fsp+4(r3)
  3685                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3686                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3687                              <1> 
  3688                              <1> 	; 04/12/2021 
  3689 000041FA 31C0                <1> 	xor	eax, eax
  3690 000041FC 8983[D86D0000]      <1>   	mov	[ebx+fsp+8], eax ; offset pointer = 0
  3691                              <1> 	;inc	word [ebx+fsp+6]
  3692 00004202 FE83[D66D0000]      <1> 	inc	byte [ebx+fsp+6] ; open count = open count + 1	
  3693                              <1> 
  3694                              <1>   	;mov	eax, ebx
  3695                              <1> 	;mov	bl, 10
  3696                              <1> 	;div	bl 
  3697                              <1> 	;	; asr r3
  3698                              <1> 	;	; asr r3 / divide by 8 
  3699                              <1> 	;	; asr r3 ; / to get number of the fsp entry-1
  3700                              <1> 	;inc	al
  3701                              <1>         ;	; inc r3 / add 1 to get fsp entry number
  3702                              <1>         ;mov	[esi+u.fp], al
  3703                              <1> 	;	; movb r3,u.fp(r2) / move entry number into 
  3704                              <1> 			; / next available slot in u.fp list
  3705                              <1> 	; 04/12/2021
  3706                              <1> 	;shr	ebx, 4	; / 16
  3707 00004208 66C1EB04            <1> 	shr	bx, 4	; bx = fsp entry number (index)	
  3708                              <1> 			; bx <= 49 for current runix 386 version
  3709 0000420C FEC3                <1> 	inc 	bl	; bl = 1 to 50
  3710 0000420E 889E[3E710000]      <1> 	mov	[esi+u.fp], bl 	
  3711                              <1> 
  3712 00004214 8935[34710000]      <1>         mov     [u.r0], esi
  3713                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3714                              <1> 			     ; / into r0 loc on stack
  3715 0000421A E9C8FAFFFF          <1>         jmp	sysret
  3716                              <1> 		; br sysret2
  3717                              <1> 
  3718                              <1> ; temporary - 26/12/2021
  3719 0000421F 08800B00            <1> openaddr: dd 0B8008h
  3720 00004223 00                  <1> bytype:	db 0 
  3721                              <1> 
  3722                              <1> 
  3723                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  3724                              <1> ;
  3725                              <1> ;         15                    7                   0
  3726                              <1> ;  1     |-------------------------------------------|
  3727                              <1> ;        |   	     i-number of open file           |
  3728                              <1> ;        |-------------------------------------------| 
  3729                              <1> ;        |        high word of 32 bit i-number       |
  3730                              <1> ;        |-------------------------------------------|
  3731                              <1> ;        | open mode & status  |   device number     |
  3732                              <1> ;        |-------------------------------------------|			
  3733                              <1> ;        |    reserved byte    |     open count      |
  3734                              <1> ;        |-------------------------------------------| 
  3735                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  3736                              <1> ;        |-------------------------------------------|
  3737                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  3738                              <1> ;        |-------------------------------------------|
  3739                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  3740                              <1> ;        |-------------------------------------------|
  3741                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  3742                              <1> ;        |-------------------------------------------|
  3743                              <1> ;  2     |                                           |
  3744                              <1> ;        |-------------------------------------------| 
  3745                              <1> ;        |                                           |
  3746                              <1> ;        |-------------------------------------------|
  3747                              <1> ;        |                                           |
  3748                              <1> ;        |-------------------------------------------|
  3749                              <1> ;        |                                           |
  3750                              <1> ;        |-------------------------------------------| 
  3751                              <1> ;        |                                           | 
  3752                              <1> 
  3753                              <1> 	;
  3754                              <1> 	; 'fsp' table (10 bytes/entry)
  3755                              <1> 	; bit 15				   bit 0
  3756                              <1> 	; ---|-------------------------------------------
  3757                              <1> 	; r/w|		i-number of open file
  3758                              <1> 	; ---|-------------------------------------------
  3759                              <1> 	;		   device number
  3760                              <1> 	; -----------------------------------------------
  3761                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3762                              <1> 	; -----------------------------------------------
  3763                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3764                              <1> 	; ----------------------|------------------------
  3765                              <1> 	;  flag that says file 	| number of processes
  3766                              <1> 	;   has been deleted	| that have file open 
  3767                              <1> 	; ----------------------|------------------------
  3768                              <1> 	;
  3769                              <1> 
  3770                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3771                              <1> syscreat: ; < create file >
  3772                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3773                              <1> 	; 04/04/2021
  3774                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3775                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3776                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3777                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3778                              <1> 	;
  3779                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3780                              <1> 	; u.namep points to name of the file and mode is put
  3781                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3782                              <1> 	; If the file aready exists, it's mode and owner remain 
  3783                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3784                              <1> 	; did not exist, an i-node is created with the new mode via
  3785                              <1> 	; 'maknod' whether or not the file already existed, it is
  3786                              <1> 	; open for writing. The fsp table is then searched for a free
  3787                              <1> 	; entry. When a free entry is found, proper data is placed
  3788                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3789                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3790                              <1> 	; is put in the user's r0. 			
  3791                              <1> 	;
  3792                              <1> 	; Calling sequence:
  3793                              <1> 	;	syscreate; name; mode
  3794                              <1> 	; Arguments:
  3795                              <1> 	;	name - name of the file to be created
  3796                              <1> 	;	mode - mode of the file to be created
  3797                              <1> 	; Inputs: (arguments)
  3798                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3799                              <1> 	;		   (the file descriptor of new file)
  3800                              <1> 	; ...............................................................
  3801                              <1> 	;				
  3802                              <1> 	; Retro UNIX 8086 v1 modification: 
  3803                              <1> 	;       'syscreate' system call has two arguments; so,
  3804                              <1> 	;	* 1st argument, name is pointed to by BX register
  3805                              <1> 	;	* 2nd argument, mode is in CX register
  3806                              <1> 	;
  3807                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3808                              <1> 	;	to the user with the file descriptor/number 
  3809                              <1> 	;	(index to u.fp list).
  3810                              <1> 	;
  3811                              <1> 	;call	arg2
  3812                              <1> 	; * name - 'u.namep' points to address of file/path name
  3813                              <1> 	;          in the user's program segment ('u.segmnt')
  3814                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3815                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3816                              <1> 	;          which is on top of stack.
  3817                              <1> 	;
  3818                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3819                              <1> 			    ; / on stack
  3820 00004224 891D[50710000]      <1> 	mov	[u.namep], ebx ; file name address
  3821                              <1> 	;push	cx ; mode
  3822                              <1> 	; 04/12/2021
  3823 0000422A 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3824 0000422B E8240A0000          <1> 	call 	namei        	
  3825                              <1> 		; jsr r0,namei / get the i-number
  3826                              <1>         ;and	ax, ax
  3827                              <1> 	;jz	short syscreat_1	       	
  3828 00004230 7226                <1> 	jc	short syscreat_1
  3829                              <1> 		; br  2f / if file doesn't exist 2f
  3830                              <1> 	; 27/12/2015
  3831                              <1> 	;cmp	ax, 41 ; device inode ?
  3832                              <1>         ;jb	syscreat_0 ; yes
  3833                              <1> 	;
  3834                              <1> 	;neg 	ax
  3835                              <1>         ;	; neg r1 / if file already exists make i-number 
  3836                              <1> 		       ; / negative (open for writing)
  3837                              <1> 	; 27/03/2021
  3838 00004232 F605[D06D0000]80    <1> 	test	byte [i.flgs], 80h ; regular file
  3839 00004239 7431                <1> 	jz	short f_create_error ; device inode !!!
  3840 0000423B F605[D06D0000]40    <1> 	test	byte [i.flgs], 40h ; directory
  3841 00004242 7528                <1> 	jnz	short f_create_error ; directory inode !!!
  3842                              <1> 
  3843                              <1> 	; Truncate existing file
  3844                              <1> ;syscreate_2:
  3845                              <1> 	; 27/03/2021
  3846                              <1> 	;xor	edx, edx ; 0
  3847                              <1> 	;inc	dl ; DL = 1 ; create/truncate (open for write)
  3848 00004244 B201                <1> 	mov	dl, 1
  3849                              <1> 	;
  3850 00004246 E8E11B0000          <1> 	call	iopen
  3851                              <1>         	; jsr r0,iopen /
  3852 0000424B E855150000          <1> 	call	itrunc
  3853                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3854                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3855                              <1> 	; 04/12/2021
  3856 00004250 59                  <1> 	pop	ecx 
  3857                              <1> syscreat_2:
  3858 00004251 B201                <1> 	mov	dl, 1 ; open for writing
  3859 00004253 E9CDFEFFFF          <1>         jmp     sysopen_1
  3860                              <1>         	; br op0
  3861                              <1> syscreat_1: ; 2: / file doesn't exist
  3862                              <1> 	;pop	ax
  3863                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3864                              <1> 	; 27/03/2021
  3865 00004258 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3866                              <1> 	;xor	ah, ah	
  3867                              <1>         ;	; bic $!377,r1 / clear upper byte
  3868                              <1> 	; 27/03/2021
  3869                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3870                              <1> 	; clear bits 15,14,13,12,9 of mode (input from user)
  3871 00004259 80E40D              <1> 	and	ah, 0Dh ; ISUID (800h) & ISGID (400h) & IREAD (100h)
  3872 0000425C 80CC8D              <1> 	or	ah, 8Dh	; IFREG (8000h) ; Regular file
  3873 0000425F E8BE0C0000          <1> 	call 	maknod
  3874                              <1>         	; jsr r0,maknod / make an i-node for this file
  3875                              <1> 	;sub	eax, eax ; 04/12/2021
  3876 00004264 66A1[70710000]      <1> 	mov	ax, [u.dirbuf]
  3877                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3878                              <1> 			        ; / for this new file in r1
  3879                              <1> 	; 04/04/2021
  3880                              <1> 	;mov	dl, 1 ; open for writing
  3881                              <1>         ;
  3882                              <1> 	;jmp	sysopen_1
  3883                              <1>         ;	; br op0 / open the file
  3884                              <1> 	; 04/04/2021
  3885 0000426A EBE5                <1> 	jmp	short syscreat_2
  3886                              <1> 
  3887                              <1> 	; 04/12/2021
  3888                              <1> dir_access_err:
  3889                              <1> 	; 14/05/2015
  3890                              <1> 	;mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3891                              <1> f_create_error:
  3892                              <1> 	; 27/03/2021
  3893 0000426C C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; permission denided !	
  3893 00004274 0000                <1>
  3894 00004276 E94CFAFFFF          <1> 	jmp	error
  3895                              <1> 
  3896                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3897                              <1> sysmkdir: ; < make directory >
  3898                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  3899                              <1> 	; 02/04/2021
  3900                              <1> 	; 27/03/2021 (Retro UNIX 386 v2 - Beginning)
  3901                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3902                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3903                              <1> 	;
  3904                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3905                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3906                              <1> 	; The special entries '.' and '..' are not present.
  3907                              <1> 	; Errors are indicated if the directory already exists or		
  3908                              <1> 	; user is not the super user. 
  3909                              <1> 	;
  3910                              <1> 	; Calling sequence:
  3911                              <1> 	;	sysmkdir; name; mode
  3912                              <1> 	; Arguments:
  3913                              <1> 	;	name - points to the name of the directory
  3914                              <1> 	;	mode - mode of the directory
  3915                              <1> 	; Inputs: (arguments)
  3916                              <1> 	; Outputs: -
  3917                              <1> 	;    (sets 'directory' flag to 1; 
  3918                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3919                              <1> 	; ...............................................................
  3920                              <1> 	;				
  3921                              <1> 	; Retro UNIX 8086 v1 modification: 
  3922                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3923                              <1> 	;	* 1st argument, name is pointed to by BX register
  3924                              <1> 	;	* 2nd argument, mode is in CX register
  3925                              <1> 	;
  3926                              <1> 		
  3927                              <1> ; / make a directory
  3928                              <1> 
  3929                              <1> 	;call	arg2
  3930                              <1> 	; * name - 'u.namep' points to address of file/path name
  3931                              <1> 	;          in the user's program segment ('u.segmnt')
  3932                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3933                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3934                              <1> 	;          which is on top of stack.
  3935                              <1> 
  3936                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3937                              <1> 			    ; / on stack
  3938 0000427B 891D[50710000]      <1> 	mov	[u.namep], ebx
  3939                              <1> 	;push	cx ; mode
  3940                              <1> 	; 27/03/2021
  3941 00004281 51                  <1> 	push	ecx ; cx = mode
  3942 00004282 E8CD090000          <1> 	call	namei
  3943                              <1>         	; jsr r0,namei / get the i-number
  3944                              <1>         	;     br .+4 / if file not found branch around error
  3945                              <1>         ;xor 	ax, ax
  3946                              <1> 	;jnz	error
  3947 00004287 7312                <1> 	jnc	short dir_exists ; 14/05/2015
  3948                              <1> 	;jnc	error	
  3949                              <1> 		; br  error2 / directory already exists (error)
  3950                              <1> 
  3951                              <1> 	;cmp	byte [u.uid], 0 ; 02/08/2013
  3952                              <1>         ;	;tstb u.uid / is user the super user
  3953                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3954                              <1> 	;;jna	error
  3955                              <1>         ;	;bne error2 / no, not allowed
  3956                              <1> 	;pop	ax
  3957                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3958                              <1> 	;and	ax, 0FFCFh ; 1111111111001111b
  3959                              <1>         ;	;bic $!317,r1 / all but su and ex
  3960                              <1> 	;;or	ax, 4000h ; 1011111111111111b
  3961                              <1> 	;or	ah, 40h ; Set bit 14 to 1
  3962                              <1>         ; 	;bis $40000,r1 / directory flag
  3963                              <1> 
  3964                              <1> 	; 02/04/2021
  3965                              <1> 	;cmp	word [u.uid], 0
  3966                              <1> 	;ja	error
  3967                              <1> 
  3968                              <1> 	; 02/04/2021
  3969                              <1> 	; ('mkdir' procedure will be called from 'maknod'
  3970                              <1> 	; and then 'mkdir' will check write access permission) 
  3971                              <1> 	; ((so, 'access_w' call is not needed here.))
  3972                              <1> 
  3973                              <1> 	;; 02/04/2021
  3974                              <1> 	;; ('make directory' user permission check)
  3975                              <1> 	;; ((current directory's write permission flags
  3976                              <1> 	;;  will be checked against user's 'uid' & gid'))
  3977                              <1> 	;mov	dx, 80h ; IWRITE
  3978                              <1> 	;call	access_w  ; (in 'access', 'u5.s')
  3979                              <1> 	;; (If cpu will return here, the user has write permission)
  3980                              <1> 		
  3981                              <1> 	; 27/03/2021
  3982 00004289 58                  <1> 	pop	eax  ; ax = mode
  3983                              <1> 	; [ii] = current directory's inode number
  3984                              <1> 
  3985                              <1> 	; 27/03/2021
  3986                              <1> 	;(ref: Retro UNIX 386 v2 inode flags,'ux.s')
  3987                              <1> 	; clear bits 13,12,11,10,9,6,3,0 of mode (input from user)
  3988                              <1> 	;and	ax, 0C1B6h  ; bits 15,14,8,7,5,4,2,1
  3989 0000428A 6625B601            <1> 	and	ax, 01B6h
  3990 0000428E 80CCC0              <1> 	or	ah, 0C0h ; IFREG (8000h) + IFDIR (4000h) 
  3991                              <1> 			 ; Directory
  3992 00004291 E88C0C0000          <1> 	call	maknod
  3993                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3994 00004296 E94CFAFFFF          <1> 	jmp	sysret
  3995                              <1>         	;br sysret2 /
  3996                              <1> dir_exists:
  3997                              <1> 	; 27/03/2021
  3998                              <1> 	; (same error number for files and directories)
  3999                              <1> 	; Error Number: 14 (ERR_DIR_EXISTS)
  4000 0000429B C705[AC710000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS
  4000 000042A3 0000                <1>
  4001                              <1> 				; 'file already exists !' error
  4002                              <1> 	; 04/12/2021
  4003 000042A5 E91DFAFFFF          <1> 	jmp	error
  4004                              <1> ;dir_access_err:
  4005                              <1> ;	; 14/05/2015
  4006                              <1> ;	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  4007                              <1> ;	jmp	error
  4008                              <1> 
  4009                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4010                              <1> sysclose: ;<close file>
  4011                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4012                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4013                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  4014                              <1> 	;
  4015                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  4016                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  4017                              <1> 	; is put in r1 and 'fclose' is called.
  4018                              <1> 	;
  4019                              <1> 	; Calling sequence:
  4020                              <1> 	;	sysclose
  4021                              <1> 	; Arguments:
  4022                              <1> 	;	-  
  4023                              <1> 	; Inputs: *u.r0 - file descriptor
  4024                              <1> 	; Outputs: -
  4025                              <1> 	; ...............................................................
  4026                              <1> 	;				
  4027                              <1> 	; Retro UNIX 8086 v1 modification:
  4028                              <1> 	;	 The user/application program puts file descriptor
  4029                              <1> 	;        in BX register as 'sysclose' system call argument.
  4030                              <1> 	; 	 (argument transfer method 1)
  4031                              <1> 
  4032                              <1> 	; / close the file
  4033                              <1> 	
  4034                              <1> 	;mov 	eax, ebx
  4035                              <1> 	; 04/12/2021
  4036                              <1> 	; ebx = file descriptor/number
  4037 000042AA E8EE080000          <1> 	call 	fclose
  4038                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  4039                              <1> 		; jsr r0,fclose / close the file
  4040                              <1>                	; br error2 / unknown file descriptor
  4041                              <1> 		; br sysret2
  4042                              <1> 	;; 14/05/2015
  4043                              <1> 	;jnc	sysret
  4044                              <1> 	; 04/12/2021
  4045 000042AF 7205                <1> 	jc	short sysclose_1
  4046 000042B1 E931FAFFFF          <1> 	jmp	sysret
  4047                              <1> sysclose_1:
  4048 000042B6 C705[AC710000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  4048 000042BE 0000                <1>
  4049 000042C0 E902FAFFFF          <1> 	jmp	error
  4050                              <1> 
  4051                              <1> 	; 19/12/2021
  4052                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4053                              <1> sysemt:
  4054                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4055                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4056                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  4057                              <1> 	;
  4058                              <1> 	; Retro UNIX 8086 v1 modification: 
  4059                              <1> 	;	'Enable Multi Tasking' system call instead 
  4060                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  4061                              <1> 	;
  4062                              <1> 	; Retro UNIX 8086 v1 feature only!
  4063                              <1> 	;	Using purpose: Kernel will start without time-out
  4064                              <1> 	;	(internal clock/timer) functionality.
  4065                              <1> 	;	Then etc/init will enable clock/timer for
  4066                              <1> 	;	multi tasking. (Then it will not be disabled again
  4067                              <1> 	;	except hardware reset/restart.)
  4068                              <1> 	;
  4069                              <1> 	
  4070                              <1> 	;cmp	byte [u.uid], 0 ; root ?
  4071                              <1> 	;;ja	error
  4072                              <1> 	;ja	badsys ; 14/05/2015
  4073                              <1> 	; 04/12/2021
  4074 000042C5 66833D[8A710000]00  <1> 	cmp	word [u.uid], 0 ; root ?
  4075 000042CD 7605                <1> 	jna	short emt_0 
  4076 000042CF E9A5FAFFFF          <1> 	jmp	badsys
  4077                              <1> emt_0:
  4078                              <1> 	; 19/12/2021
  4079                              <1> 	;cli
  4080 000042D4 21DB                <1> 	and	ebx, ebx
  4081 000042D6 740F                <1> 	jz	short emt_2
  4082                              <1> 	; Enable multi tasking -time sharing-
  4083 000042D8 B8[C5510000]        <1> 	mov	eax, clock
  4084                              <1> emt_1:
  4085 000042DD A3[11080000]        <1> 	mov	[x_timer], eax
  4086                              <1> 	;sti
  4087 000042E2 E900FAFFFF          <1> 	jmp	sysret
  4088                              <1> emt_2:
  4089                              <1> 	; Disable multi tasking -time sharing-
  4090 000042E7 B8[19080000]        <1> 	mov	eax, u_timer
  4091 000042EC EBEF                <1> 	jmp	short emt_1
  4092                              <1> 
  4093                              <1> 	; Original UNIX v1 'sysemt' routine
  4094                              <1> ;sysemt:
  4095                              <1>         ;
  4096                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  4097                              <1> 			 ; / in loc 30
  4098                              <1>         ;cmp    30,$core / was the argument a lower address 
  4099                              <1> 			; / than core
  4100                              <1>         ;blo    1f / yes, rtssym
  4101                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  4102                              <1> 			; / and less than "ecore"
  4103                              <1>         ;blo    2f / yes, sysret2
  4104                              <1> ;1:
  4105                              <1>         ;mov    $rtssym,30
  4106                              <1> ;2:
  4107                              <1>         ;br     sysret2
  4108                              <1> 
  4109                              <1> sysilgins:
  4110                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  4111                              <1> 	; 03/06/2013
  4112                              <1> 	; Retro UNIX 8086 v1 modification: 
  4113                              <1> 	;	not a valid system call ! (not in use)
  4114                              <1> 	;
  4115 000042EE E986FAFFFF          <1> 	jmp	badsys
  4116                              <1> 	;jmp	error
  4117                              <1> 	;;jmp 	sysret
  4118                              <1> 
  4119                              <1> 	; Original UNIX v1 'sysemt' routine
  4120                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  4121                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  4122                              <1> 			  ;/ put it in loc 8.,
  4123                              <1>         ;cmp    10,$core / making it the illegal instruction 
  4124                              <1> 		       ; / trap address
  4125                              <1>         ;blo    1f / is the address a user core address?  
  4126                              <1> 		; / yes, go to 2f
  4127                              <1>         ;cmp    10,$ecore
  4128                              <1>         ;blo    2f
  4129                              <1> ;1:
  4130                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  4131                              <1> 		    ; / instruction trap address for the system
  4132                              <1> ;2:
  4133                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  4134                              <1> 
  4135                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  4136                              <1> sysmdate: ; < change the modification time of a file >
  4137                              <1> 	; 24/12/2021
  4138                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  4139                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  4140                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4141                              <1> 	;
  4142                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  4143                              <1> 	; file into core. The user is checked if he is the owner 
  4144                              <1> 	; or super user. If he is neither an error occurs.
  4145                              <1> 	; 'setimod' is then called to set the i-node modification
  4146                              <1> 	; byte and the modification time, but the modification time
  4147                              <1> 	; is overwritten by whatever get put on the stack during
  4148                              <1> 	; a 'systime' system call. This calls are restricted to
  4149                              <1> 	; the super user.		
  4150                              <1> 	;
  4151                              <1> 	; Calling sequence:
  4152                              <1> 	;	sysmdate; name
  4153                              <1> 	; Arguments:
  4154                              <1> 	;	name - points to the name of file
  4155                              <1> 	; Inputs: (arguments)
  4156                              <1> 	; Outputs: -
  4157                              <1> 	; ...............................................................
  4158                              <1> 	;				
  4159                              <1> 	; Retro UNIX 8086 v1 modification: 
  4160                              <1> 	;	 The user/application program puts address 
  4161                              <1> 	;	 of the file name in BX register 
  4162                              <1> 	;	 as 'sysmdate' system call argument.
  4163                              <1> 	;
  4164                              <1> ; / change the modification time of a file
  4165                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  4166 000042F3 891D[50710000]      <1>         mov	[u.namep], ebx
  4167 000042F9 E856090000          <1> 	call	namei
  4168                              <1> 		; jsr r0,namei / get its i-number
  4169                              <1> 	;;jc	error       
  4170                              <1> 	;	; br error2 / no, such file
  4171                              <1> 	;jc	fnotfound ; file not found !
  4172                              <1> 	; 24/12/2021
  4173 000042FE 7305                <1> 	jnc	short mdate_0
  4174 00004300 E942FEFFFF          <1> 	jmp	fnotfound
  4175                              <1> mdate_0: 
  4176 00004305 E8DD120000          <1> 	call	iget
  4177                              <1> 		; jsr r0,iget / get i-node into core
  4178                              <1> 	;mov	al, [u.uid]
  4179                              <1> 	;cmp	al, [i.uid]
  4180                              <1>         ;	; cmpb u.uid,i.uid / is user same as owner
  4181                              <1> 	;je	short mdate_1
  4182                              <1>         ;	; beq 1f / yes
  4183                              <1> 	;and	al, al
  4184                              <1> 	;	; tstb u.uid / no, is user the super user
  4185                              <1> 	;;jnz	error
  4186                              <1> 	;	; bne error2 / no, error
  4187                              <1> 	;jz	short mdate_1
  4188                              <1> 	; 04/12/2021
  4189 0000430A 66A1[8A710000]      <1> 	mov	ax, [u.uid]
  4190 00004310 663B05[D46D0000]    <1> 	cmp	ax, [i.uid]
  4191 00004317 7414                <1> 	je	short mdate_1	
  4192 00004319 6621C0              <1> 	and	ax, ax
  4193 0000431C 740F                <1> 	jz	short mdate_1
  4194                              <1> 
  4195 0000431E C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4195 00004326 0000                <1>
  4196 00004328 E99AF9FFFF          <1> 	jmp	error
  4197                              <1> mdate_1: ;1:
  4198 0000432D E851140000          <1> 	call	setimod
  4199                              <1>         	; jsr r0,setimod / fill in modification data,
  4200                              <1> 		               ; / time etc.
  4201 00004332 BE[80700000]        <1> 	mov	esi, p_time
  4202 00004337 BF[086E0000]        <1> 	mov	edi, i.mtim
  4203 0000433C A5                  <1> 	movsd
  4204                              <1> 		; mov 4(sp),i.mtim / move present time to
  4205                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4206 0000433D E9A5F9FFFF          <1>         jmp	sysret
  4207                              <1> 		; br sysret2
  4208                              <1> 
  4209                              <1> sysstty: ; < set tty status and mode >
  4210                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4211                              <1> 	;	    ((32 bit reg push/pop))
  4212                              <1> 	; 17/11/2015
  4213                              <1> 	; 12/11/2015
  4214                              <1> 	; 29/10/2015
  4215                              <1> 	; 17/10/2015
  4216                              <1> 	; 13/10/2015
  4217                              <1> 	; 29/06/2015
  4218                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4219                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4220                              <1> 	;
  4221                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4222                              <1> 	; whose file descriptor is in (u.r0).
  4223                              <1> 	;
  4224                              <1> 	; Calling sequence:
  4225                              <1> 	;	sysstty; arg
  4226                              <1> 	; Arguments:
  4227                              <1> 	;	arg - address of 3 consequitive words that contain
  4228                              <1> 	;	      the source of status data	
  4229                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4230                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4231                              <1> 	; ...............................................................
  4232                              <1> 	;	
  4233                              <1> 	; Retro UNIX 8086 v1 modification: 
  4234                              <1> 	;	'sysstty' system call will set the tty
  4235                              <1> 	;	(clear keyboard buffer and set cursor position)
  4236                              <1> 	;	 in following manner:
  4237                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4238                              <1> 	;
  4239                              <1> 	; Inputs:
  4240                              <1> 	;	BX = 0 --> means
  4241                              <1> 	;	   If CL = FFh
  4242                              <1> 	;	      set cursor position for console tty, only 
  4243                              <1> 	;	      CH will be ignored (char. will not be written)	
  4244                              <1> 	;	   If CH = 0 (CL < FFh)
  4245                              <1> 	;	      set console tty for (current) process
  4246                              <1> 	;	      CL = tty number (0 to 9)
  4247                              <1> 	;	      (If CH = 0, character will not be written)			
  4248                              <1> 	;          If CH > 0 (CL < FFh)	
  4249                              <1> 	;             CL = tty number (0 to 9)
  4250                              <1> 	;	      CH = character will be written
  4251                              <1> 	;	        at requested cursor position (in DX)	
  4252                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4253                              <1>   	;		(only tty number 0 to 7) 
  4254                              <1> 	;          DL = communication parameters (for serial ports) 
  4255                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4256                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4257                              <1> 	;			or set cursor position	
  4258                              <1> 	;	   DH = 0FFh -> DL is not valid
  4259                              <1> 	;		do not set serial port parameters 
  4260                              <1> 	;		or do not set cursor position
  4261                              <1> 	;
  4262                              <1> 	;	BX > 0 --> points to name of tty
  4263                              <1> 	;    	   CH > 0 -->
  4264                              <1> 	;		CH = character will be written in current 
  4265                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4266                              <1> 	;	     	or character will be sent to serial port
  4267                              <1> 	;	     	(for tty number 8 or 9)
  4268                              <1> 	;		CL = color of the character if tty number < 8.
  4269                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4270                              <1> 	;		set mode (tty 8 to 9) or 
  4271                              <1> 	;		set current cursor positions (tty 0 to 7) only. 
  4272                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4273                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4274                              <1> 	;		(DL is not valid)
  4275                              <1> 	;	   DL = communication parameters 
  4276                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4277                              <1> 	; Outputs:
  4278                              <1> 	;	cf = 0 -> OK
  4279                              <1> 	;	     AL = tty number (0 to 9)
  4280                              <1> 	;	     AH = line status if tty number is 8 or 9
  4281                              <1> 	;	     AH = process number (of the caller) 	
  4282                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4283                              <1> 	;	     AH = FFh if the tty is locked 
  4284                              <1> 	;		  (owned by another process)
  4285                              <1> 	;	        = process number (of the caller) 
  4286                              <1> 	;		  (if < FFh and tty number < 8)
  4287                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4288                              <1> 	;	     AH = line status if tty number is 8 or 9
  4289                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4290                              <1> 	;
  4291                              <1> 	; 27/06/2015 (32 bit modifications)
  4292                              <1> 	; 14/01/2014
  4293 00004342 31C0                <1> 	xor 	eax, eax
  4294 00004344 6648                <1> 	dec	ax ; 17/10/2015
  4295 00004346 A3[34710000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4296 0000434B 21DB                <1> 	and	ebx, ebx
  4297                              <1>         ;jnz	sysstty_6
  4298                              <1> 	; 24/12/2021
  4299 0000434D 7405                <1> 	jz	short sysstty_14
  4300 0000434F E9C7000000          <1> 	jmp	sysstty_6
  4301                              <1> sysstty_14:
  4302                              <1> 	; set console tty
  4303                              <1> 	; 29/10/2015
  4304                              <1> 	; 17/01/2014 
  4305 00004354 80F909              <1> 	cmp	cl, 9
  4306 00004357 7613                <1> 	jna	short sysstty_0
  4307                              <1> 	; 17/11/2015
  4308 00004359 80F9FF              <1> 	cmp	cl, 0FFh
  4309 0000435C 7202                <1> 	jb	short sysstty_13
  4310 0000435E 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4311                              <1> sysstty_13:
  4312 00004360 8A1D[89710000]      <1> 	mov	bl, [u.uno] ; process number
  4313 00004366 8A8B[6F6E0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4314                              <1> sysstty_0:
  4315                              <1> 	; 29/06/2015
  4316 0000436C 52                  <1> 	push	edx ; 24/12/2021
  4317 0000436D 51                  <1> 	push	ecx
  4318 0000436E 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4319 00004370 88C8                <1> 	mov	al, cl
  4320 00004372 A2[34710000]        <1> 	mov	[u.r0], al ; tyy number (0 to 9)
  4321 00004377 E8731B0000          <1> 	call	ottyp
  4322 0000437C 59                  <1> 	pop	ecx
  4323 0000437D 5A                  <1> 	pop	edx
  4324                              <1> 	;
  4325 0000437E 7256                <1> 	jc	short sysstty_pd_err
  4326                              <1> 	;
  4327 00004380 80F908              <1> 	cmp	cl, 8
  4328 00004383 7220                <1> 	jb	short sysstty_2
  4329                              <1> 	;
  4330 00004385 80FEFF              <1> 	cmp	dh, 0FFh
  4331 00004388 741B                <1> 	je	short sysstty_2
  4332                              <1> 	; set communication parameters for serial ports
  4333                              <1> 	; 29/10/2015
  4334 0000438A 88D4                <1> 	mov	ah, dl ; communication parameters
  4335                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4336                              <1> 		;			 THRE int + RDA int 
  4337                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4338                              <1> 		;			 THRE int + RDA int 
  4339 0000438C 28C0                <1> 	sub	al, al ; 0
  4340                              <1> 	; 12/07/2014
  4341 0000438E 80F909              <1> 	cmp	cl, 9
  4342 00004391 7202                <1> 	jb	short sysstty_1
  4343 00004393 FEC0                <1> 	inc	al
  4344                              <1> sysstty_1:
  4345 00004395 51                  <1> 	push	ecx ; 24/12/2021
  4346                              <1> 	; 29/06/2015	
  4347 00004396 E8C6F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4348 0000439B 66890D[35710000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4349                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4350 000043A2 59                  <1> 	pop	ecx
  4351 000043A3 7267                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4352                              <1> sysstty_2:
  4353                              <1> 	; 17/01/2014
  4354 000043A5 20ED                <1> 	and	ch, ch 	; set cursor position 
  4355                              <1> 			; or comm. parameters ONLY
  4356 000043A7 750D                <1> 	jnz	short sysstty_3
  4357 000043A9 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4358 000043B0 888B[6F6E0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4359                              <1> sysstty_3:
  4360                              <1> 	; 16/01/2014
  4361 000043B6 88E8                <1> 	mov	al, ch ; character  ; 0 to FFh
  4362                              <1> 	; 17/11/2015
  4363 000043B8 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4364 000043BA 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4365                              <1>         ;jna	sysstty_9
  4366                              <1> 	; 24/12/2021
  4367 000043BC 7705                <1> 	ja	short sysstty_12
  4368 000043BE E9BE000000          <1> 	jmp	sysstty_9
  4369                              <1> sysstty_12:
  4370                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4371                              <1> 	; (Set specified serial port as console tty port)
  4372                              <1> 	; CH = character to be written
  4373                              <1> 	; 15/04/2014
  4374                              <1> 	; CH = 0 --> initialization only
  4375                              <1> 	; AL = character
  4376                              <1> 	; 26/06/2014
  4377 000043C3 880D[6D710000]      <1> 	mov	[u.ttyn], cl
  4378                              <1> 	; 12/07/2014
  4379 000043C9 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4380 000043CB 20C0                <1> 	and	al, al
  4381 000043CD 7416                <1> 	jz	short sysstty_4 ; al = ch = 0
  4382                              <1>  	; 04/07/2014
  4383 000043CF E861210000          <1> 	call 	sndc
  4384                              <1> 	; 12/07/2014
  4385 000043D4 EB1B                <1> 	jmp	short sysstty_5
  4386                              <1> sysstty_pd_err: ; 29/06/2015
  4387                              <1> 	; 'permission denied !' error
  4388 000043D6 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4388 000043DE 0000                <1>
  4389 000043E0 E9E2F8FFFF          <1> 	jmp	error
  4390                              <1> sysstty_4:
  4391                              <1> 	; 12/07/2014
  4392                              <1> 	;xchg 	ah, al	; al = 0 -> al = ah, ah = 0
  4393 000043E5 88E0                <1> 	mov	al, ah ; 29/06/2015
  4394 000043E7 2C08                <1> 	sub	al, 8
  4395                              <1> 	; 27/06/2015
  4396 000043E9 E86BF3FFFF          <1> 	call	sp_status ; get serial port status
  4397                              <1> 	; AL = Line status, AH = Modem status
  4398                              <1> 	; 12/11/2015
  4399 000043EE 3C80                <1> 	cmp	al, 80h
  4400 000043F0 F5                  <1> 	cmc
  4401                              <1> sysstty_5:
  4402 000043F1 66A3[35710000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4403                              <1> 		     ; EAX bits 16-23 = modem status	
  4404 000043F7 9C                  <1> 	pushf
  4405 000043F8 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4406 000043FA A0[6D710000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4407 000043FF E80C1C0000          <1> 	call	cttyp
  4408 00004404 9D                  <1> 	popf
  4409                              <1> 	;jnc	sysret	
  4410                              <1> 	; 24/12/2021
  4411 00004405 7205                <1> 	jc	short sysstty_tmout_err
  4412 00004407 E9DBF8FFFF          <1> 	jmp	sysret
  4413                              <1> 	; time out error 
  4414                              <1> sysstty_tmout_err:
  4415 0000440C C705[AC710000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4415 00004414 0000                <1>
  4416 00004416 E9ACF8FFFF          <1> 	jmp	error
  4417                              <1> sysstty_6:
  4418 0000441B 52                  <1> 	push	edx ; 24/12/2021
  4419 0000441C 51                  <1> 	push	ecx
  4420 0000441D 891D[50710000]      <1> 	mov	[u.namep], ebx
  4421 00004423 E82C080000          <1> 	call	namei
  4422 00004428 59                  <1> 	pop	ecx
  4423 00004429 5A                  <1> 	pop	edx
  4424 0000442A 720E                <1> 	jc	short sysstty_inv_dn
  4425                              <1> 	;
  4426 0000442C 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4427 00004430 7708                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4428                              <1> 	;
  4429 00004432 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4430                              <1> 		       ; /dev/COM1, /dev/COM2
  4431 00004434 7213                <1> 	jb	short sysstty_7
  4432 00004436 2C0A                <1> 	sub	al, 10
  4433 00004438 EB20                <1> 	jmp	short sysstty_8
  4434                              <1> sysstty_inv_dn: 
  4435                              <1> 	; 27/06/2015
  4436                              <1> 	; Invalid device name (not a tty) ! error
  4437                              <1> 	; (Device is not a tty or device name not found)
  4438 0000443A C705[AC710000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4438 00004442 0000                <1>
  4439 00004444 E97EF8FFFF          <1> 	jmp	error 
  4440                              <1> sysstty_7:
  4441 00004449 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4442 0000444B 75ED                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4443 0000444D 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4444 00004454 8A83[6F6E0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4445                              <1> sysstty_8:	
  4446 0000445A A2[34710000]        <1> 	mov	[u.r0], al
  4447 0000445F 52                  <1> 	push	edx ; 24/12/2021
  4448 00004460 50                  <1> 	push	eax
  4449 00004461 51                  <1> 	push	ecx	
  4450 00004462 E8881A0000          <1> 	call	ottyp
  4451 00004467 59                  <1> 	pop	ecx
  4452 00004468 58                  <1> 	pop	eax
  4453 00004469 5A                  <1> 	pop	edx
  4454                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4455                              <1> 	; 24/12/2021
  4456 0000446A 7305                <1> 	jnc	short sysstty_15
  4457                              <1> 	; 'permission denied !'
  4458 0000446C E965FFFFFF          <1> 	jmp	sysstty_pd_err
  4459                              <1> sysstty_15:
  4460                              <1> 	; 29/10/2015
  4461 00004471 86E9                <1> 	xchg 	ch, cl
  4462                              <1> 		; cl = character, ch = color code
  4463 00004473 86C1                <1> 	xchg	al, cl
  4464                              <1> 		; al = character, cl = tty number
  4465 00004475 80F907              <1> 	cmp	cl, 7
  4466                              <1> 	;ja	sysstty_12
  4467                              <1> 	; 24/12/2021
  4468 00004478 7605                <1> 	jna	short sysstty_16
  4469 0000447A E944FFFFFF          <1> 	jmp	sysstty_12
  4470                              <1> sysstty_16:
  4471                              <1> 	; 16/01/2014
  4472 0000447F 30FF                <1> 	xor	bh, bh
  4473                              <1> 	;
  4474                              <1> sysstty_9: 	; tty 0 to tty 7
  4475                              <1> 	; al = character
  4476 00004481 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4477 00004484 740B                <1> 	je	short sysstty_10
  4478 00004486 51                  <1> 	push	ecx ; 24/12/2021
  4479 00004487 50                  <1> 	push	eax	
  4480                              <1> 	;movzx, ebx, cl
  4481 00004488 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4482 0000448A E852D1FFFF          <1> 	call	set_cpos
  4483 0000448F 58                  <1> 	pop	eax
  4484 00004490 59                  <1> 	pop	ecx
  4485                              <1> sysstty_10: 
  4486                              <1> 	; 29/10/2015
  4487 00004491 08C0                <1> 	or	al, al ; character
  4488 00004493 740D                <1> 	jz      short sysstty_11 ; al = 0
  4489                              <1> 	; 17/11/2015
  4490 00004495 3CFF                <1> 	cmp	al, 0FFh
  4491 00004497 7309                <1> 	jnb	short sysstty_11
  4492                              <1> 		; ch > 0 and ch < FFh
  4493                              <1> 	; write a character at current cursor position
  4494 00004499 88EC                <1> 	mov	ah, ch ; color/attribute
  4495                              <1> 	; 12/07/2014
  4496 0000449B 51                  <1> 	push	ecx ; 24/12/2021
  4497 0000449C E87ED2FFFF          <1> 	call	write_c_current
  4498 000044A1 59                  <1> 	pop	ecx
  4499                              <1> sysstty_11:
  4500                              <1> 	; 14/01/2014
  4501 000044A2 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4502                              <1> 	; 18/01/2014
  4503                              <1> 	;movzx	eax, cl ; 27/06/2015
  4504 000044A4 88C8                <1> 	mov	al, cl
  4505 000044A6 E8651B0000          <1> 	call	cttyp
  4506 000044AB E937F8FFFF          <1> 	jmp	sysret
  4507                              <1> 
  4508                              <1> ; Original UNIX v1 'sysstty' routine:
  4509                              <1> ; gtty:
  4510                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4511                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4512                              <1> 	; 		/ r2 has source
  4513                              <1>         ;mov    r2,-(sp)
  4514                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4515                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4516                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4517                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4518                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4519                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4520                              <1>         ;       br .+4 / list empty, skip branch
  4521                              <1>         ;br     1b / get another character until list is empty
  4522                              <1>         ;mov    0b,r1 / move cc offset to r1
  4523                              <1>         ;inc    r1 / bump it for output clist
  4524                              <1>         ;tstb   cc(r1) / is it 0
  4525                              <1>         ;beq    1f / yes, no characters to output
  4526                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4527                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4528                              <1>         ;br     1b / try to calm it down again
  4529                              <1> ;1:
  4530                              <1>         ;mov    (sp)+,r1
  4531                              <1>         ;mov    (sp)+,r2 / restore registers
  4532                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4533                              <1>         ;beq    1f / if 0, 1f
  4534                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4535                              <1>         ;                   / control status register
  4536                              <1> ;1:
  4537                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4538                              <1>         ;beq    1f / if 0 1f
  4539                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4540                              <1> 	;		    / control status reg
  4541                              <1> ;1:
  4542                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4543                              <1>         ;jmp     sysret2 / return to user
  4544                              <1> 
  4545                              <1> sysgtty: ; < get tty status >
  4546                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4547                              <1> 	;	    ((32 bit reg push/pop))
  4548                              <1> 	; 23/11/2015
  4549                              <1> 	; 29/10/2015
  4550                              <1> 	; 17/10/2015
  4551                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4552                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4553                              <1> 	;
  4554                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4555                              <1> 	; It stores in the three words addressed by it's argument
  4556                              <1> 	; the status of the typewriter whose file descriptor
  4557                              <1> 	; in (u.r0).
  4558                              <1> 	;
  4559                              <1> 	; Calling sequence:
  4560                              <1> 	;	sysgtty; arg
  4561                              <1> 	; Arguments:
  4562                              <1> 	;	arg - address of 3 words destination of the status
  4563                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4564                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4565                              <1> 	; ...............................................................
  4566                              <1> 	;	
  4567                              <1> 	; Retro UNIX 8086 v1 modification: 
  4568                              <1> 	;	'sysgtty' system call will return status of tty
  4569                              <1> 	;	(keyboard, serial port and video page status)
  4570                              <1> 	;	 in following manner:
  4571                              <1> 	;
  4572                              <1> 	; Inputs:
  4573                              <1> 	;	BX = 0 --> means 
  4574                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4575                              <1> 	;	                 for (current) process
  4576                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4577                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4578                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4579                              <1> 	;	     CH > 0 -->	tty number + 1
  4580                              <1> 	;
  4581                              <1> 	;	BX > 0 --> points to name of tty
  4582                              <1> 	;	     CL = 0 --> return keyboard status
  4583                              <1> 	;	     CL = 1 --> return video page status
  4584                              <1> 	;	     CH = undefined		 
  4585                              <1> 	;
  4586                              <1> 	; Outputs:
  4587                              <1> 	;	cf = 0 ->
  4588                              <1> 	;
  4589                              <1> 	;	     AL = tty number from 0 to 9
  4590                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4591                              <1> 	;	     AH = 0 if the tty is free/unused
  4592                              <1> 	;	     AH = the process number of the caller 
  4593                              <1>  	;	     AH = FFh if the tty is locked by another process
  4594                              <1> 	;
  4595                              <1> 	;	  (if calling is for serial port status)
  4596                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4597                              <1> 	;		  (BH = modem status, BL = Line status)
  4598                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4599                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4600                              <1> 	;
  4601                              <1> 	;	  (if calling is for keyboard status)
  4602                              <1> 	;	     BX = current character in tty/keyboard buffer
  4603                              <1> 	;		  (BH = scan code, BL = ascii code)
  4604                              <1> 	;		  (BX=0 if there is not a waiting character)
  4605                              <1> 	;	     CX  is undefined
  4606                              <1> 	;
  4607                              <1> 	;	  (if calling is for video page status)	
  4608                              <1> 	;	     BX = cursor position on the video page
  4609                              <1> 	;		  if tty number < 8
  4610                              <1> 	;		  (BH = row, BL = column)
  4611                              <1> 	;	     CX = current character (in cursor position)
  4612                              <1> 	;		  on the video page of the tty 
  4613                              <1> 	;		  if tty number < 8
  4614                              <1> 	;		  (CH = color, CL = character)
  4615                              <1> 	;	
  4616                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4617                              <1> 	;
  4618                              <1> 	;	     AH = FFh if the caller is not owner of
  4619                              <1> 	;		  specified tty or console tty
  4620                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4621                              <1> 	;	     BX, CX are undefined if cf = 1
  4622                              <1> 	;
  4623                              <1> 	;	  (If tty number is 8 or 9)
  4624                              <1> 	;	     AL = tty number 
  4625                              <1> 	;	     AH = the process number of the caller 
  4626                              <1> 	;	     BX = serial port status
  4627                              <1> 	;  		 (BH = modem status, BL = Line status)
  4628                              <1> 	;	     CX = 0
  4629                              <1> 	;
  4630                              <1> 		
  4631                              <1> gtty:   ; get (requested) tty number
  4632                              <1> 	; 17/10/2015
  4633                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4634                              <1> 	; 30/05/2013 - 12/07/2014
  4635                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4636                              <1> 	;
  4637                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4638                              <1> 	;
  4639                              <1> 	; 28/06/2015 (32 bit modifications)
  4640                              <1> 	; 16/01/2014
  4641 000044B0 31C0                <1> 	xor 	eax, eax
  4642 000044B2 6648                <1> 	dec	ax ; 17/10/2015
  4643 000044B4 A3[34710000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4644 000044B9 80F901              <1> 	cmp	cl, 1
  4645 000044BC 760F                <1> 	jna	short sysgtty_0
  4646                              <1> sysgtty_invp:
  4647                              <1> 	; 28/06/2015
  4648 000044BE C705[AC710000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4648 000044C6 0000                <1>
  4649 000044C8 E9FAF7FFFF          <1> 	jmp	error
  4650                              <1> sysgtty_0:	
  4651 000044CD 21DB                <1> 	and	ebx, ebx
  4652 000044CF 742E                <1> 	jz	short sysgtty_1
  4653                              <1> 	;
  4654 000044D1 891D[50710000]      <1> 	mov	[u.namep], ebx
  4655                              <1> 	;push	cx ; 23/11/2015
  4656 000044D7 51                  <1> 	push	ecx ; 24/12/2021
  4657 000044D8 E877070000          <1> 	call	namei
  4658 000044DD 59                  <1> 	pop	ecx
  4659                              <1> 	;pop	cx ; 23/11/2015
  4660 000044DE 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4661                              <1> 	;
  4662 000044E0 6683F801            <1> 	cmp	ax, 1
  4663 000044E4 7622                <1> 	jna	short sysgtty_2
  4664 000044E6 6683E80A            <1> 	sub	ax, 10
  4665 000044EA 6683F809            <1> 	cmp	ax, 9
  4666                              <1> 	;ja	short sysgtty_inv_dn
  4667                              <1> 	;mov	ch, al
  4668                              <1> 	;jmp	short sysgtty_4
  4669                              <1> 	; 23/11/2015
  4670 000044EE 7629                <1> 	jna	short sysgtty_4
  4671                              <1> sysgtty_inv_dn: 
  4672                              <1> 	; 28/06/2015
  4673                              <1> 	; Invalid device name (not a tty) ! error
  4674                              <1> 	; (Device is not a tty or device name not found)
  4675 000044F0 C705[AC710000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4675 000044F8 0000                <1>
  4676 000044FA E9C8F7FFFF          <1> 	jmp	error 
  4677                              <1> sysgtty_1:
  4678                              <1> 	; 16/01/2014
  4679 000044FF 80FD0A              <1> 	cmp	ch, 10
  4680 00004502 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4681 00004504 FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4682 00004506 790F                <1> 	jns	short sysgtty_3 ; not negative
  4683                              <1> 	;
  4684                              <1> sysgtty_2:
  4685                              <1> 	; get tty number of console tty
  4686 00004508 8A25[89710000]      <1> 	mov	ah, [u.uno]
  4687                              <1>  	; 28/06/2015
  4688 0000450E 0FB6DC              <1> 	movzx 	ebx, ah
  4689 00004511 8AAB[6F6E0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4690                              <1> sysgtty_3:
  4691 00004517 88E8                <1> 	mov	al, ch
  4692                              <1> sysgtty_4:
  4693 00004519 A2[34710000]        <1> 	mov	[u.r0], al
  4694                              <1>  	; 28/06/2015
  4695                              <1> 	;cmp	al, 9
  4696                              <1> 	;ja	short sysgtty_invp
  4697 0000451E 8B2D[30710000]      <1> 	mov	ebp, [u.usp]
  4698                              <1> 	; 23/11/2015
  4699 00004524 20C9                <1> 	and	cl, cl
  4700 00004526 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4701 00004528 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4702 0000452A 722E                <1> 	jb	short sysgtty_6 ; video page status
  4703                              <1> 	; serial port status
  4704                              <1> 	; 12/07/2014
  4705                              <1> 	;mov	dx, 0
  4706                              <1> 	;je	short sysgtty_5
  4707                              <1> 	;inc	dl
  4708                              <1> ;sysgtty_5:
  4709                              <1> 	; 28/06/2015
  4710 0000452C 2C08                <1> 	sub	al, 8
  4711 0000452E E826F2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4712                              <1> 	; AL = Line status, AH = Modem status
  4713 00004533 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4714 00004537 8A25[89710000]      <1> 	mov	ah, [u.uno]
  4715 0000453D 8825[35710000]      <1>         mov     [u.r0+1], ah
  4716                              <1> 	; 24/12/2021
  4717 00004543 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4718                              <1> 				; (in ECX)
  4719 00004549 A880                <1> 	test	al, 80h
  4720 0000454B 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4721 0000454D A801                <1> 	test	al, 1
  4722                              <1> 	;jz	sysret
  4723 0000454F 7404                <1> 	jz	short sysgtty_10
  4724 00004551 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4725                              <1> sysgtty_10:
  4726 00004555 E98DF7FFFF          <1> 	jmp	sysret
  4727                              <1> sysgtty_6:
  4728 0000455A A2[6D710000]        <1> 	mov	[u.ttyn], al ; tty number
  4729                              <1> 	;movzx	ebx, al
  4730 0000455F 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4731 00004561 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4732                              <1> 	; 22/04/2014 - 29/06/2015
  4733 00004563 81C3[84700000]      <1>         add     ebx, ttyl
  4734 00004569 8A23                <1>  	mov	ah, [ebx]
  4735 0000456B 3A25[89710000]      <1> 	cmp	ah, [u.uno]
  4736 00004571 7404                <1> 	je	short sysgtty_7
  4737 00004573 20E4                <1> 	and	ah, ah
  4738                              <1> 	;jz	short sysgtty_7
  4739 00004575 7506                <1> 	jnz	short sysgtty_8
  4740                              <1> 	;mov	ah, 0FFh
  4741                              <1> sysgtty_7:
  4742 00004577 8825[35710000]      <1>         mov     [u.r0+1], ah
  4743                              <1> sysgtty_8:
  4744 0000457D 08C9                <1> 	or	cl, cl
  4745 0000457F 7510                <1> 	jnz	short sysgtty_9
  4746 00004581 B001                <1> 	mov	al, 1  ; test a key is available
  4747 00004583 E8301F0000          <1> 	call	getc
  4748 00004588 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4749 0000458C E956F7FFFF          <1> 	jmp	sysret
  4750                              <1> sysgtty_9:
  4751 00004591 8A1D[6D710000]      <1> 	mov	bl, [u.ttyn]
  4752                              <1> 	; bl = video page number
  4753 00004597 E88F200000          <1> 	call 	get_cpos
  4754                              <1> 	; dx = cursor position
  4755 0000459C 66895510            <1> 	mov	[ebp+16], dx ; bx
  4756                              <1> 	;mov	bl, [u.ttyn]
  4757                              <1> 	; bl = video page number
  4758 000045A0 E897200000          <1> 	call	read_ac_current
  4759                              <1> 	; ax = character and attribute/color
  4760 000045A5 66894518            <1> 	mov	[ebp+24], ax ; cx
  4761 000045A9 E939F7FFFF          <1> 	jmp	sysret
  4762                              <1> sysgtty_dnr_err:
  4763                              <1> 	; 'device not responding !' error	
  4764                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4765 000045AE C705[AC710000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4765 000045B6 0000                <1>
  4766 000045B8 E90AF7FFFF          <1> 	jmp	error	
  4767                              <1> 
  4768                              <1> ; Original UNIX v1 'sysgtty' routine:
  4769                              <1> ; sysgtty:
  4770                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4771                              <1> 	;	       / r2 has destination
  4772                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4773                              <1> 	;                     / in 1st word of dest
  4774                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4775                              <1> 	;                     / in 2nd word of dest
  4776                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4777                              <1>         ;jmp    sysret2 / return to user
  4778                              <1> 	
  4779                              <1> ; Original UNIX v1 'gtty' routine:
  4780                              <1> ; gtty:
  4781                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4782                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4783                              <1>         ;jsr    r0,getf / get the i-number of the file
  4784                              <1>         ;tst    r1 / is it open for reading
  4785                              <1>         ;bgt    1f / yes
  4786                              <1>         ;neg    r1 / no, i-number is negative, 
  4787                              <1> 	;          / so make it positive
  4788                              <1> ;1:
  4789                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4790                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4791                              <1>         ;bhis   error9 / no, error
  4792                              <1>         ;asl    r1 / 0%2
  4793                              <1>         ;asl    r1 / 0%4 / yes
  4794                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4795                              <1> 	;	       ; / tty block
  4796                              <1>         ;mov    u.off,r2 / put argument in r2
  4797                              <1>         ;rts    r0 / return
  2021                                  %include 'u2.s'      ; 11/05/2015
  2022                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2023                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2024                              <1> ; ****************************************************************************
  2025                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS2.INC
  2026                              <1> ; Last Modification: 27/12/2021
  2027                              <1> ; ----------------------------------------------------------------------------
  2028                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2029                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2030                              <1> ;
  2031                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2032                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2033                              <1> ; <Bell Laboratories (17/3/1972)>
  2034                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2035                              <1> ;
  2036                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2037                              <1> ;
  2038                              <1> ; ****************************************************************************
  2039                              <1> 
  2040                              <1> syslink:
  2041                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2042                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2043                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2044                              <1> 	;
  2045                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2046                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2047                              <1> 	; given to the entry that will go in the current directory.
  2048                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2049                              <1> 	; in the name 2 entry of current directory is the same
  2050                              <1> 	; i-number for the name 1 file.
  2051                              <1> 	;
  2052                              <1> 	; Calling sequence:
  2053                              <1> 	;	syslink; name 1; name 2
  2054                              <1> 	; Arguments:
  2055                              <1> 	;	name 1 - file name to which link will be created.
  2056                              <1> 	;	name 2 - name of entry in current directory that
  2057                              <1> 	;		 links to name 1.
  2058                              <1> 	; Inputs: -
  2059                              <1> 	; Outputs: -
  2060                              <1> 	; ...............................................................
  2061                              <1> 	;	
  2062                              <1> 	; Retro UNIX 8086 v1 modification: 
  2063                              <1> 	;       'syslink' system call has two arguments; so,
  2064                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2065                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2066                              <1> 	;
  2067                              <1> 		; / name1, name2
  2068                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2069 000045BD 891D[50710000]      <1> 	mov	[u.namep], ebx
  2070 000045C3 51                  <1> 	push	ecx
  2071 000045C4 E88B060000          <1> 	call	namei
  2072                              <1> 		; jsr r0,namei / find the i-number associated with
  2073                              <1> 			     ; / the 1st path name
  2074                              <1>      	;;and	ax, ax
  2075                              <1> 	;;jz	error ; File not found
  2076                              <1> 	;jc	error 
  2077                              <1> 		; br error9 / cannot be found
  2078 000045C9 730F                <1> 	jnc	short syslink0
  2079                              <1> 	;pop 	ecx
  2080                              <1> 	; 'file not found !' error
  2081 000045CB C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2081 000045D3 0000                <1>
  2082 000045D5 E9EDF6FFFF          <1> 	jmp	error
  2083                              <1> syslink0:
  2084 000045DA E808100000          <1> 	call	iget
  2085                              <1> 		; jsr r0,iget / get the i-node into core
  2086 000045DF 8F05[50710000]      <1> 	pop	dword [u.namep] ; ecx
  2087                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2088                              <1> 	; 24/12/2021
  2089 000045E5 50                  <1> 	push	eax ; *
  2090                              <1> 	;push	ax
  2091                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2092                              <1> 			    ; / (a link to this file is to be created)
  2093                              <1> 	; 24/12/2021
  2094 000045E6 8A0D[15710000]      <1> 	mov	cl, [cdev]
  2095 000045EC 51                  <1> 	push	ecx ; **
  2096                              <1> 	;push	word [cdev]
  2097                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2098 000045ED E852000000          <1> 	call	isdir
  2099                              <1> 		; jsr r0,isdir / is it a directory
  2100 000045F2 E85D060000          <1> 	call	namei
  2101                              <1> 		; jsr r0,namei / no, get i-number of name2
  2102                              <1> 	;jnc	error
  2103                              <1> 		; br .+4   / not found 
  2104                              <1> 			 ; / so r1 = i-number of current directory
  2105                              <1> 			 ; / ii = i-number of current directory
  2106                              <1> 		; br error9 / file already exists., error
  2107 000045F7 720F                <1> 	jc	short syslink1
  2108                              <1> 	; pop eax ; 24/12/2021
  2109                              <1> 	; pop eax
  2110                              <1> 	; 'file exists !' error
  2111 000045F9 C705[AC710000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2111 00004601 0000                <1>
  2112 00004603 E9BFF6FFFF          <1> 	jmp	error
  2113                              <1> syslink1:
  2114                              <1> 	;pop	cx
  2115                              <1> 	; 24/12/2021
  2116 00004608 59                  <1> 	pop	ecx ; **
  2117                              <1> 	;cmp	cx, [cdev]
  2118 00004609 3A0D[15710000]      <1> 	cmp	cl, [cdev]
  2119                              <1> 	;jne	error
  2120                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2121                              <1> 			       ; / end of current directory
  2122                              <1> 	        ; bne error9
  2123 0000460F 740F                <1> 	je	short syslink2
  2124                              <1> 	; 'not same drive !' error
  2125 00004611 C705[AC710000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2125 00004619 0000                <1>
  2126 0000461B E9A7F6FFFF          <1> 	jmp	error
  2127                              <1> syslink2:
  2128                              <1> 	;pop	eax ; 24/12/2021
  2129                              <1> 	;push	eax
  2130                              <1> 	; 24/12/2021
  2131 00004620 8B0424              <1> 	mov	eax, [esp] ; *
  2132 00004623 66A3[70710000]      <1> 	mov	[u.dirbuf], ax
  2133                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2134 00004629 E8A0000000          <1> 	call	mkdir
  2135                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2136                              <1> 		 	     ; / in current directory
  2137                              <1> 	; 24/12/2021
  2138 0000462E 58                  <1> 	pop	eax ; *
  2139                              <1> 	;pop	ax
  2140                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2141 0000462F E8B30F0000          <1> 	call	iget
  2142                              <1> 		; jsr r0,iget / get i-node into core
  2143 00004634 FE05[D26D0000]      <1> 	inc	byte [i.nlks]
  2144                              <1> 		; incb i.nlks / add 1 to its number of links
  2145 0000463A E844110000          <1> 	call	setimod
  2146                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2147 0000463F E9A3F6FFFF          <1> 	jmp	sysret
  2148                              <1> 
  2149                              <1> isdir:
  2150                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2151                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2152                              <1> 	;
  2153                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2154                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2155                              <1> 	;  called by syslink and sysunlink to make sure directories
  2156                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2157                              <1> 	; 'isdir' does not bother checking. The current i-node
  2158                              <1> 	;  is not disturbed.			
  2159                              <1> 	;		
  2160                              <1> 	; INPUTS ->
  2161                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2162                              <1> 	;    u.uid - user id
  2163                              <1> 	; OUTPUTS ->
  2164                              <1> 	;    r1 - contains current i-number upon exit
  2165                              <1> 	;    	 (current i-node back in core) 
  2166                              <1> 	;	
  2167                              <1> 	; ((AX = R1))
  2168                              <1> 	;
  2169                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2170                              <1> 	;
  2171                              <1> 
  2172                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2173                              <1> 	; / there is an error unless super user made the call
  2174                              <1> 	
  2175 00004644 803D[8A710000]00    <1> 	cmp	byte [u.uid], 0 
  2176                              <1> 		; tstb u.uid / super user
  2177 0000464B 762D                <1> 	jna	short isdir1
  2178                              <1> 		; beq 1f / yes, don't care
  2179 0000464D 66FF35[10710000]    <1> 	push	word [ii]
  2180                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2181 00004654 E88E0F0000          <1> 	call	iget
  2182                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2183 00004659 66F705[D06D0000]00- <1> 	test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2183 00004661 40                  <1>
  2184                              <1> 		; bit $40000,i.flgs / is it a directory
  2185                              <1> 	;jnz	error
  2186                              <1> 		; bne error9 / yes, error
  2187 00004662 740F                <1> 	jz	short isdir0
  2188 00004664 C705[AC710000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2188 0000466C 0000                <1>
  2189                              <1> 				; 'permission denied !' error
  2190                              <1> 	; pop	ax
  2191 0000466E E954F6FFFF          <1> 	jmp	error	
  2192                              <1> isdir0:	
  2193 00004673 6658                <1> 	pop	ax
  2194                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2195 00004675 E86D0F0000          <1> 	call	iget
  2196                              <1> 		; jsr r0,iget / get it back in
  2197                              <1> isdir1: ; 1:
  2198 0000467A C3                  <1> 	retn
  2199                              <1> 		; rts r0
  2200                              <1> 
  2201                              <1> sysunlink:
  2202                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2203                              <1> 	; 04/12/2015 (14 byte file names)
  2204                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2205                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2206                              <1> 	;
  2207                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2208                              <1> 	; name from its directory. If this entry was the last link
  2209                              <1> 	; to the file, the contents of the file are freed and the
  2210                              <1> 	; file is destroyed. If, however, the file was open in any
  2211                              <1> 	; process, the actual destruction is delayed until it is 
  2212                              <1> 	; closed, even though the directory entry has disappeared.
  2213                              <1> 	; 
  2214                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2215                              <1> 	; does not exist or that its directory can not be written.
  2216                              <1> 	; Write permission is not required on the file itself.
  2217                              <1> 	; It is also illegal to unlink a directory (except for
  2218                              <1> 	; the superuser).
  2219                              <1> 	;
  2220                              <1> 	; Calling sequence:
  2221                              <1> 	;	sysunlink; name
  2222                              <1> 	; Arguments:
  2223                              <1> 	;	name - name of directory entry to be removed 
  2224                              <1> 	; Inputs: -
  2225                              <1> 	; Outputs: -
  2226                              <1> 	; ...............................................................
  2227                              <1> 	;				
  2228                              <1> 	; Retro UNIX 8086 v1 modification:
  2229                              <1> 	;	 The user/application program puts address of the name
  2230                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2231                              <1> 
  2232                              <1> 	; / name - remove link name
  2233 0000467B 891D[50710000]      <1> 	mov	[u.namep], ebx
  2234                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2235 00004681 E8CE050000          <1> 	call	namei
  2236                              <1> 		; jsr r0,namei / find the i-number associated 
  2237                              <1> 			     ; / with the path name
  2238                              <1> 	;jc	error
  2239                              <1> 		; br error9 / not found
  2240 00004686 730F                <1> 	jnc	short sysunlink1
  2241                              <1> 	; 'file not found !' error
  2242 00004688 C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2242 00004690 0000                <1>
  2243 00004692 E930F6FFFF          <1> 	jmp	error
  2244                              <1> sysunlink1:
  2245 00004697 50                  <1> 	push	eax ; 24/12/2021
  2246                              <1> 	;push	ax
  2247                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2248 00004698 E8A7FFFFFF          <1> 	call	isdir
  2249                              <1> 		; jsr r0,isdir / is it a directory
  2250                              <1> 	;xor 	ax, ax
  2251                              <1> 	; 24/12/2021
  2252 0000469D 31C0                <1> 	xor	eax, eax
  2253 0000469F 66A3[70710000]      <1> 	mov	[u.dirbuf], ax ; 0
  2254                              <1> 		; clr u.dirbuf / no, clear the location that will
  2255                              <1> 			   ; / get written into the i-number portion
  2256                              <1> 			 ; / of the entry
  2257 000046A5 832D[54710000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2258                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2259 000046AC E868000000          <1> 	call	wdir
  2260                              <1> 		; jsr r0,wdir / free the directory entry
  2261 000046B1 58                  <1> 	pop	eax ; 24/12/2021
  2262                              <1> 	;pop	ax
  2263                              <1> 		; mov (sp)+,r1 / get i-number back
  2264 000046B2 E8300F0000          <1> 	call	iget
  2265                              <1> 		; jsr r0,iget / get i-node
  2266 000046B7 E8C7100000          <1> 	call	setimod
  2267                              <1> 		; jsr r0,setimod / set modified flag
  2268 000046BC FE0D[D26D0000]      <1> 	dec	byte [i.nlks]
  2269                              <1> 		; decb i.nlks / decrement the number of links
  2270                              <1> 	; 24/12/2021
  2271 000046C2 7505                <1> 	jnz	short sysunlink_2
  2272                              <1> 	;jnz	sysret
  2273                              <1> 		; bgt sysret9 / if this was not the last link
  2274                              <1> 			    ; / to file return
  2275                              <1> 	; AX = r1 = i-number
  2276 000046C4 E8AB090000          <1> 	call	anyi
  2277                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2278                              <1> 			 ; / Then free contents of file and destroy it.
  2279                              <1> sysunlink_2:
  2280 000046C9 E919F6FFFF          <1> 	jmp	sysret
  2281                              <1> 		; br sysret9
  2282                              <1> 
  2283                              <1> mkdir:
  2284                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2285                              <1> 	; 04/12/2015 (14 byte directory names)
  2286                              <1> 	; 12/10/2015
  2287                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2288                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2289                              <1> 	;
  2290                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2291                              <1> 	; by u.namep into the current directory.
  2292                              <1> 	;
  2293                              <1> 	; INPUTS ->
  2294                              <1> 	;    u.namep - points to a file name 
  2295                              <1> 	;	           that is about to be a directory entry.
  2296                              <1> 	;    ii - current directory's i-number.	
  2297                              <1> 	; OUTPUTS ->
  2298                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2299                              <1> 	;    u.off - points to entry to be filled 
  2300                              <1> 	;	     in the current directory		
  2301                              <1> 	;    u.base - points to start of u.dirbuf.
  2302                              <1> 	;    r1 - contains i-number of current directory 
  2303                              <1> 	;	
  2304                              <1> 	; ((AX = R1)) output
  2305                              <1> 	;
  2306                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2307                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2308                              <1> 	;
  2309                              <1> 
  2310                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2311 000046CE 31C0                <1> 	xor 	eax, eax
  2312 000046D0 BF[72710000]        <1> 	mov     edi, u.dirbuf+2
  2313 000046D5 89FE                <1> 	mov	esi, edi
  2314 000046D7 AB                  <1> 	stosd
  2315 000046D8 AB                  <1> 	stosd
  2316                              <1> 	; 04/12/2015 (14 byte directory names)
  2317 000046D9 AB                  <1> 	stosd
  2318 000046DA 66AB                <1> 	stosw
  2319                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2320 000046DC 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2321                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2322                              <1> 	;mov 	ebp, [u.namep]
  2323 000046DE E894060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2324                              <1> 		; esi = physical address (page start + offset)
  2325                              <1> 		; ecx = byte count in the page (1 - 4096)
  2326                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2327                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2328                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2329                              <1> mkdir_1: ; 1: 
  2330 000046E3 45                  <1> 	inc	ebp ; 12/10/2015
  2331                              <1> 	;
  2332                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2333                              <1> 	 ; 01/08/2013
  2334 000046E4 AC                  <1> 	lodsb
  2335                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2336 000046E5 20C0                <1> 	and 	al, al
  2337 000046E7 7426                <1> 	jz 	short mkdir_3 	  
  2338                              <1> 		; beq 1f / if null, done
  2339 000046E9 3C2F                <1> 	cmp	al, '/'
  2340                              <1> 		; cmp r1,$'/ / is it a "/"?
  2341 000046EB 7413                <1> 	je	short mkdir_err
  2342                              <1> 	;je	error
  2343                              <1> 		; beq error9 / yes, error
  2344                              <1> 	; 12/10/2015
  2345                              <1> 	;dec	cx
  2346 000046ED 49                  <1> 	dec	ecx ; 24/12/2021
  2347 000046EE 7505                <1> 	jnz	short mkdir_2
  2348                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2349 000046F0 E888060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2350                              <1> 		; esi = physical address (page start + offset)
  2351                              <1> 		; ecx = byte count in the page
  2352                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2353                              <1> mkdir_2:
  2354 000046F5 81FF[80710000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2355                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2356                              <1> 				     ; / a char?
  2357 000046FB 74E6                <1> 	je	short mkdir_1
  2358                              <1> 		; beq 1b / yes, go back
  2359 000046FD AA                  <1> 	stosb
  2360                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2361 000046FE EBE3                <1> 	jmp 	short mkdir_1
  2362                              <1> 		; br 1b / get next char
  2363                              <1> mkdir_err:
  2364                              <1> 	; 17/06/2015
  2365 00004700 C705[AC710000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2365 00004708 0000                <1>
  2366 0000470A E9B8F5FFFF          <1> 	jmp	error
  2367                              <1> 
  2368                              <1> mkdir_3: ; 1:
  2369 0000470F A1[4C710000]        <1> 	mov	eax, [u.dirp]
  2370 00004714 A3[54710000]        <1> 	mov	[u.off], eax
  2371                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2372                              <1> 				 ; / slot to u.off
  2373                              <1> wdir:	; 24/12/2021 (Retro UNIX 386 v1.2)
  2374                              <1> 	; 29/04/2013
  2375 00004719 C705[5C710000]-     <1>         mov     dword [u.base], u.dirbuf
  2375 0000471F [70710000]          <1>
  2376                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2377 00004723 C705[60710000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2377 0000472B 0000                <1>
  2378                              <1> 		; mov $10.,u.count / u.count = 10
  2379 0000472D 66A1[10710000]      <1> 	mov	ax, [ii] 
  2380                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2381 00004733 B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2382 00004735 E8940F0000          <1> 	call 	access
  2383                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2384                              <1> 				 ; / for writing
  2385                              <1> 	; AX = i-number of current directory
  2386                              <1> 	; 01/08/2013
  2387 0000473A FE05[AA710000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2388                              <1> 	;call	writei
  2389                              <1> 	;	; jsr r0,writei / write into directory
  2390                              <1> 	;retn	
  2391                              <1> 	;	; rts r0
  2392                              <1> 	; 24/12/2021
  2393 00004740 E91C130000          <1> 	jmp	writei
  2394                              <1> 
  2395                              <1> 	; 24/12/2021
  2396                              <1> 	; 11/12/2021
  2397                              <1> 	; 04/12/2021
  2398                              <1> 	; 30/11/2021
  2399                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2400                              <1> sysexec:
  2401                              <1> 	; 02/05/2021
  2402                              <1> 	; 27/03/2021
  2403                              <1> 	; 26/03/2021
  2404                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  2405                              <1> 	; 23/10/2015
  2406                              <1> 	; 10/10/2015, 18/10/2015, 19/10/2015
  2407                              <1> 	; 29/07/2015, 05/08/2015, 05/08/2015
  2408                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2409                              <1> 	; 01/07/2015, 02/07/2015, 20/07,2015
  2410                              <1> 	; 24/06/2015, 25/06/2021
  2411                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2412                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2413                              <1> 	;
  2414                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2415                              <1> 	; pointed to by 'name' in the sysexec call. 
  2416                              <1> 	; 'sysexec' performs the following operations:
  2417                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2418                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2419                              <1> 	;    3. sets trap vectors to system routines.
  2420                              <1> 	;    4. loads arguments to be passed to executing file into
  2421                              <1> 	;	highest locations of user's core
  2422                              <1> 	;    5. puts pointers to arguments in locations immediately
  2423                              <1> 	;	following arguments.
  2424                              <1> 	;    6.	saves number of arguments in next location.
  2425                              <1> 	;    7. initializes user's stack area so that all registers
  2426                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2427                              <1> 	;	to core when 'sysret' restores registers 
  2428                              <1> 	;	and does an rti.
  2429                              <1> 	;    8. inializes u.r0 and u.sp
  2430                              <1> 	;    9. zeros user's core down to u.r0
  2431                              <1> 	;   10.	reads executable file from storage device into core
  2432                              <1> 	;	starting at location 'core'.
  2433                              <1> 	;   11.	sets u.break to point to end of user's code with
  2434                              <1> 	;	data area appended.
  2435                              <1> 	;   12.	calls 'sysret' which returns control at location
  2436                              <1> 	;	'core' via 'rti' instruction.
  2437                              <1> 	;
  2438                              <1> 	; Calling sequence:
  2439                              <1> 	;	sysexec; namep; argp
  2440                              <1> 	; Arguments:
  2441                              <1> 	;	namep - points to pathname of file to be executed
  2442                              <1> 	;	argp  - address of table of argument pointers
  2443                              <1> 	;	argp1... argpn - table of argument pointers
  2444                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2445                              <1> 	; Inputs: (arguments)
  2446                              <1> 	; Outputs: -	
  2447                              <1> 	; ...............................................................
  2448                              <1> 	;
  2449                              <1> 	; Retro UNIX 386 v1 modification: 
  2450                              <1> 	;	User application runs in it's own virtual space 
  2451                              <1> 	;	which is izolated from kernel memory (and other
  2452                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2453                              <1> 	;	privilige mode. Virtual start address is always 0.
  2454                              <1> 	;	User's core memory starts at linear address 400000h
  2455                              <1> 	;	(the end of the 1st 4MB).
  2456                              <1> 	;
  2457                              <1> 	; Retro UNIX 8086 v1 modification: 
  2458                              <1> 	;	user/application segment and system/kernel segment
  2459                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2460                              <1> 	;	are different (user's registers are saved to 
  2461                              <1> 	;	and then restored from system's stack.)
  2462                              <1> 	;
  2463                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2464                              <1> 	;	      arguments which were in these registers;
  2465                              <1> 	;	      but, it returns by putting the 1st argument
  2466                              <1> 	;	      in 'u.namep' and the 2nd argument
  2467                              <1> 	;	      on top of stack. (1st argument is offset of the
  2468                              <1> 	;	      file/path name in the user's program segment.)
  2469                              <1> 	
  2470                              <1> 	;call	arg2
  2471                              <1> 	; * name - 'u.namep' points to address of file/path name
  2472                              <1> 	;          in the user's program segment ('u.segmnt')
  2473                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2474                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2475                              <1> 	;          which is on top of stack.
  2476                              <1> 	;
  2477                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2478                              <1> 
  2479                              <1> 	; 23/06/2015 (32 bit modifications)
  2480                              <1> 
  2481 00004745 891D[50710000]      <1> 	mov	[u.namep], ebx ; argument 1
  2482                              <1>         ; 18/10/2015
  2483 0000474B 890D[04720000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2484 00004751 E8FE040000          <1> 	call	namei
  2485                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2486                              <1> 			     ; / named in sysexec call in r1
  2487                              <1> 	;jc	error
  2488                              <1> 		; br error9
  2489 00004756 7322                <1> 	jnc	short sysexec_0
  2490                              <1> 
  2491                              <1> ; temporary - 11/12/2021
  2492 00004758 C70500800B00344E34- <1> mov	dword [0B8000h], 4E344E34h
  2492 00004761 4E                  <1>
  2493 00004762 B9FFFF0F00          <1> mov	ecx, 0FFFFFh
  2494                              <1> abovez:
  2495 00004767 4A                  <1> dec	edx
  2496 00004768 42                  <1> inc	edx
  2497 00004769 E2FC                <1> loop	abovez
  2498                              <1> 
  2499                              <1> 	;
  2500                              <1> 	; 'file not found !' error
  2501 0000476B C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2501 00004773 0000                <1>
  2502 00004775 E94DF5FFFF          <1> 	jmp	error
  2503                              <1> 
  2504                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2505                              <1> 	; (executable file flag is checked in 'access')
  2506                              <1> 	; (following error message is in 'access' subroutine)
  2507                              <1> ;sysexec_not_exf:
  2508                              <1> 	;; 'not executable file !' error
  2509                              <1> 	;mov	dword [u.error], ERR_NOT_EXECUTABLE
  2510                              <1> 	;jmp	error 
  2511                              <1> sysexec_0:
  2512                              <1> ; temporary - 28/11/2021
  2513 0000477A C70500800B00314E31- <1> mov	dword [0B8000h], 4E314E31h
  2513 00004783 4E                  <1>
  2514 00004784 B9FFFF0F00          <1> mov	ecx, 0FFFFFh
  2515                              <1> above1:
  2516 00004789 4A                  <1> dec	edx
  2517 0000478A 42                  <1> inc	edx
  2518 0000478B E2FC                <1> loop	above1
  2519                              <1> 
  2520                              <1> 	; 26/03/2021 ('iget' will be called in 'access')
  2521                              <1> 	;call	iget
  2522                              <1> 	;	; jsr r0,iget / get i-node for file to be executed
  2523                              <1> 	;
  2524                              <1> 	;test	byte [i.flgs], 10h
  2525                              <1> 	;;test	word [i.flgs], 10h
  2526                              <1> 	;	; bit $20,i.flgs / is file executable
  2527                              <1> 	;jz	short sysexec_not_exf
  2528                              <1> 	;;jz	error
  2529                              <1> 	;	; beq error9
  2530                              <1> 	; 26/03/2021
  2531 0000478D 66BA4000            <1> 	mov	dx, 40h ; IEXEC - execute, owner
  2532 00004791 E8380F0000          <1> 	call	access
  2533                              <1> 	; ! we are here because there is execute permission !
  2534                              <1> 	; ('iopen' is not needed for regular files, from now on)
  2535                              <1> 
  2536                              <1> 	; 26/03/2021
  2537                              <1> 	;; 25/03/2021
  2538                              <1> 	;; (ref: Retro UNIX 386 v2, 'ux.s')
  2539                              <1> 	;mov	dx, 40h ; IEXEC - execute, owner
  2540                              <1> 	;;
  2541                              <1> 	;call	iopen
  2542                              <1> 	;	; jsr r0,iopen / gets i-node for file with i-number
  2543                              <1> 	;		     ; / given in r1 (opens file)
  2544                              <1> 	
  2545                              <1> 	; 26/03/2021
  2546                              <1> 	; AX = i-number of the file
  2547                              <1> 	;test	byte [i.flgs], 20h
  2548                              <1> 	;;test	word [i.flgs], 20h
  2549                              <1> 	;	; bit $40,i.flgs / test user id on execution bit
  2550                              <1> 	;jz	short sysexec_1
  2551                              <1> 	;	; beq 1f
  2552                              <1> 	;cmp 	byte [u.uid], 0 ; 02/08/2013
  2553                              <1> 	;	; tstb u.uid / test user id
  2554                              <1> 	;jna	short sysexec_1
  2555                              <1> 	;	; beq 1f / super user
  2556                              <1> 
  2557                              <1> 	;mov	cl, [i.uid]
  2558                              <1> 	;mov	[u.uid], cl ; 02/08/2013
  2559                              <1> 	;	; movb i.uid,u.uid / put user id of owner of file
  2560                              <1> 				 ; / as process user id
  2561                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2562 00004796 A0[D16D0000]        <1> 	mov	al, [i.flgs+1]
  2563 0000479B 66833D[8A710000]00  <1> 	cmp	word [u.uid], 0	; super user (root) ?
  2564                              <1> 	;jna	short sysexec_19 ; yes, super user
  2565                              <1> 	;; 02/05/2021
  2566 000047A3 7620                <1> 	jna	short sysexec_1	; don't set UID or GID
  2567                              <1> 
  2568                              <1> 	; test set user id on execution bit 
  2569 000047A5 A808                <1> 	test	al, 08h ; ISUID flag (800h)
  2570                              <1> 	;jz	short sysexec_19
  2571                              <1> 	; 02/05/2021
  2572 000047A7 741C                <1> 	jz	short sysexec_1 ; do not set group ID
  2573                              <1> 				; (if user ID will not be set)
  2574                              <1> 				; (02/05/2021)	
  2575                              <1> 	; set user id on exec (800h)
  2576                              <1> 	; 26/03/2021
  2577                              <1> sysexec_setuid:
  2578                              <1> 	;; 27/03/2021
  2579                              <1> 	;cmp	word [u.uid], 0
  2580                              <1> 	;;jna	short sysexec_19 ; super user
  2581                              <1> 	;; 02/05/2021
  2582                              <1> 	;jna	short sysexec_1 ; do not set group ID
  2583                              <1> 	;			; (if user ID will not be set)
  2584                              <1> 	;			; (02/05/2021)
  2585 000047A9 668B0D[D46D0000]    <1> 	mov	cx, [i.uid]
  2586 000047B0 66890D[8A710000]    <1> 	mov	[u.uid], cx
  2587                              <1> sysexec_19:
  2588                              <1> 	; test set group id on execution bit 
  2589 000047B7 A804                <1> 	test	al, 04h ; ISGID flag (400h)
  2590 000047B9 740A                <1> 	jz	short sysexec_1
  2591                              <1> sysexec_setgid:
  2592                              <1> 	; set group id on exec (400h)
  2593 000047BB A0[D66D0000]        <1> 	mov	al, [i.gid]
  2594 000047C0 A2[8E710000]        <1> 	mov	[u.gid], al
  2595                              <1> 	;
  2596                              <1> sysexec_1:
  2597                              <1> 	; 24/12/2021
  2598                              <1> 	; 11/12/2021
  2599                              <1> 	; 04/12/2021
  2600                              <1> 	; 18/10/2015
  2601                              <1> 	; 10/10/2015
  2602                              <1> 	; 24/07/2015
  2603                              <1> 	; 21/07/2015
  2604                              <1> 	; 25/06/2015
  2605                              <1> 	; 24/06/2015
  2606                              <1>         ; Moving arguments to the end of [u.upage]
  2607                              <1> 	; (by regarding page borders in user's memory space)
  2608                              <1> 	;
  2609                              <1> 	; 10/10/2015
  2610                              <1> 	; 21/07/2015
  2611 000047C5 89E5                <1> 	mov	ebp, esp ; (**)
  2612                              <1> 	; 18/10/2015
  2613 000047C7 89EF                <1> 	mov 	edi, ebp
  2614 000047C9 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2615                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2616 000047CE 29CF                <1> 	sub	edi, ecx
  2617 000047D0 89FC                <1> 	mov	esp, edi
  2618 000047D2 31C0                <1> 	xor	eax, eax
  2619 000047D4 A3[64710000]        <1> 	mov 	[u.nread], eax ; 0
  2620 000047D9 49                  <1> 	dec	ecx ; 256 - 1
  2621 000047DA 890D[60710000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2622                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2623                              <1> 	; 24/12/2021
  2624                              <1> sysexec_2:
  2625 000047E0 8B35[04720000]      <1> 	mov	esi, [argv] ; 18/10/2015
  2626 000047E6 E85A020000          <1> 	call	get_argp
  2627 000047EB B904000000          <1> 	mov	ecx, 4 ; mov ecx, 4
  2628                              <1> sysexec_3:
  2629 000047F0 21C0                <1> 	and	eax, eax
  2630 000047F2 7454                <1> 	jz	short sysexec_6
  2631                              <1> 	; 18/10/2015
  2632 000047F4 010D[04720000]      <1> 	add	[argv], ecx ; 4
  2633                              <1> 	;inc	word [argc]
  2634                              <1> 	; 11/12/2021
  2635 000047FA FF05[00720000]      <1> 	inc	dword [argc]
  2636                              <1> 	;
  2637 00004800 A3[5C710000]        <1> 	mov	[u.base], eax
  2638                              <1>  	; 23/10/2015
  2639 00004805 66C705[A4710000]00- <1> 	mov	word [u.pcount], 0
  2639 0000480D 00                  <1>
  2640                              <1> sysexec_4:
  2641 0000480E E809140000          <1> 	call	cpass ; get a character from user's core memory
  2642 00004813 750B                <1>         jnz	short sysexec_5
  2643                              <1> 		; (max. 255 chars + null)
  2644                              <1> 	; 18/10/2015
  2645 00004815 28C0                <1> 	sub 	al, al
  2646 00004817 AA                  <1> 	stosb
  2647 00004818 FF05[64710000]      <1> 	inc	dword [u.nread]
  2648 0000481E EB28                <1> 	jmp	short sysexec_6
  2649                              <1> sysexec_5:
  2650 00004820 AA                  <1> 	stosb
  2651 00004821 20C0                <1> 	and 	al, al
  2652 00004823 75E9                <1> 	jnz	short sysexec_4
  2653 00004825 B904000000          <1> 	mov	ecx, 4
  2654 0000482A 390D[FC710000]      <1> 	cmp	[ncount], ecx ; 4
  2655 00004830 72AE                <1> 	jb	short sysexec_2
  2656 00004832 8B35[F8710000]      <1> 	mov	esi, [nbase]
  2657 00004838 010D[F8710000]      <1> 	add	[nbase], ecx ; 4	
  2658                              <1> 	;sub	[ncount], cx 
  2659                              <1> 	; 11/12/2021
  2660 0000483E 290D[FC710000]      <1> 	sub	[ncount], ecx
  2661 00004844 8B06                <1> 	mov	eax, [esi]
  2662 00004846 EBA8                <1> 	jmp	short sysexec_3
  2663                              <1> sysexec_6:
  2664                              <1> 	; 24/12/2021
  2665                              <1> 	; 18/10/2015
  2666                              <1> 	; argument list transfer from user's core memory to
  2667                              <1> 	; kernel stack frame is OK here.
  2668                              <1> 	; [u.nread] = ; argument list length
  2669                              <1> 	;mov	[argv], esp ; start address of argument list
  2670                              <1> 	;
  2671                              <1> 	; 18/10/2015
  2672                              <1> 	; 24/07/2015
  2673                              <1>         ; 21/07/2015
  2674                              <1> 	; 02/07/2015
  2675                              <1> 	; 25/06/2015
  2676                              <1> 	; 24/06/2015
  2677                              <1> 	; 23/06/2015
  2678                              <1> 	;
  2679 00004848 8B1D[9C710000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2680 0000484E 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2681 00004850 740A                <1> 	jz	short sysexec_7
  2682 00004852 A1[98710000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2683 00004857 E844E8FFFF          <1> 	call	deallocate_page_dir
  2684                              <1> sysexec_7:
  2685 0000485C E874E7FFFF          <1> 	call	make_page_dir
  2686                              <1> 	;jc	short sysexec_14
  2687                              <1> 	;jc	panic  ; allocation error 
  2688                              <1> 	;	       ; after a deallocation would be nonsence !?
  2689                              <1> 	; 26/03/2021
  2690 00004861 7243                <1> 	jc	short sysexec_panic
  2691                              <1> 	
  2692                              <1> 	; 24/07/2015
  2693                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2694                              <1> 	;     of the user's page directory
  2695                              <1> 	;     (It is needed for interrupts!)
  2696                              <1> 	; 18/10/2015
  2697 00004863 8B15[38700000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2698 00004869 8B02                <1> 	mov	eax, [edx] ; physical address of
  2699                              <1> 			   ; kernel's first page table (1st 4 MB)
  2700                              <1> 			   ; (PDE 0 of kernel's page directory)
  2701 0000486B 8B15[98710000]      <1> 	mov 	edx, [u.pgdir]
  2702 00004871 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2703                              <1> 	;
  2704                              <1> 	; 20/07/2015
  2705 00004873 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2706                              <1> 	; 18/10/2015
  2707 00004878 BE[F0710000]        <1> 	mov	esi, pcore ; physical start address
  2708                              <1> sysexec_8:	
  2709 0000487D B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2710 00004882 E86CE7FFFF          <1> 	call	make_page_table
  2711                              <1> 	;jc	panic
  2712                              <1> 	; 26/03/2021
  2713 00004887 721D                <1> 	jc	short sysexec_panic
  2714                              <1> 	;
  2715                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2716 00004889 E873E7FFFF          <1> 	call	make_page ; make new page, clear and set the pte
  2717                              <1> 	;jc	panic
  2718                              <1> 	; 26/03/2021
  2719 0000488E 7216                <1> 	jc	short sysexec_panic
  2720                              <1> 	;
  2721 00004890 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2722                              <1> 	; ebx = virtual address (24/07/2015)
  2723                              <1> 	; 30/11/2021
  2724                              <1> 	;call 	add_to_swap_queue
  2725                              <1> 	; 18/10/2015
  2726 00004892 81FE[F4710000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2727 00004898 7411                <1> 	je	short sysexec_9 ; yes
  2728 0000489A BE[F4710000]        <1> 	mov	esi, ecore  ; physical address of the last page
  2729                              <1> 	; 20/07/2015
  2730 0000489F BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2731                              <1> 	; ebx = virtual end address + segment base address - 4K
  2732 000048A4 EBD7                <1>         jmp     short sysexec_8
  2733                              <1> sysexec_panic:
  2734                              <1> 	; 26/03/2021
  2735 000048A6 E9A3ECFFFF          <1> 	jmp	panic
  2736                              <1> 
  2737                              <1> sysexec_9:
  2738                              <1> 	; 11/12/2021
  2739                              <1> 	; 18/10/2015
  2740                              <1> 	; 26/08/2015
  2741                              <1> 	; 25/06/2015
  2742                              <1> 	; move arguments from kernel stack to [ecore]
  2743                              <1> 	; (argument list/line will be copied from kernel stack
  2744                              <1> 	; frame to the last (stack) page of user's core memory)
  2745                              <1> 	; 18/10/2015
  2746 000048AB 8B3D[F4710000]      <1> 	mov	edi, [ecore]
  2747 000048B1 81C700100000        <1> 	add	edi, PAGE_SIZE
  2748                              <1> 	;movzx	eax, word [argc]
  2749                              <1> 	; 11/12/2021
  2750 000048B7 A1[00720000]        <1> 	mov	eax, [argc]
  2751 000048BC 09C0                <1> 	or	eax, eax
  2752 000048BE 7509                <1> 	jnz	short sysexec_10
  2753 000048C0 89FB                <1> 	mov 	ebx, edi
  2754 000048C2 83EB04              <1> 	sub	ebx, 4 
  2755 000048C5 8903                <1> 	mov	[ebx], eax ; 0
  2756 000048C7 EB40                <1> 	jmp 	short sysexec_13
  2757                              <1> sysexec_10:
  2758 000048C9 8B0D[64710000]      <1> 	mov	ecx, [u.nread]
  2759                              <1> 	;mov 	esi, [argv]
  2760 000048CF 89E6                <1> 	mov	esi, esp ; start address of argument list
  2761 000048D1 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2762 000048D3 89C2                <1> 	mov	edx, eax
  2763 000048D5 FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2764 000048D7 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2765 000048DA 89FB                <1> 	mov	ebx, edi
  2766 000048DC 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2767 000048DF 29D3                <1> 	sub 	ebx, edx
  2768 000048E1 89FA                <1> 	mov	edx, edi
  2769 000048E3 F3A4                <1> 	rep	movsb
  2770 000048E5 89D6                <1> 	mov 	esi, edx
  2771 000048E7 89DF                <1> 	mov 	edi, ebx
  2772 000048E9 BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2773 000048EE 2B15[F4710000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2774 000048F4 AB                  <1> 	stosd	; eax = argument count
  2775                              <1> sysexec_11:
  2776 000048F5 89F0                <1> 	mov	eax, esi
  2777 000048F7 01D0                <1> 	add	eax, edx
  2778 000048F9 AB                  <1> 	stosd  ; eax = virtual address
  2779 000048FA FE0D[00720000]      <1> 	dec	byte [argc]
  2780 00004900 7407                <1> 	jz	short sysexec_13
  2781                              <1> sysexec_12:
  2782 00004902 AC                  <1> 	lodsb
  2783 00004903 20C0                <1> 	and	al, al
  2784 00004905 75FB                <1> 	jnz	short sysexec_12
  2785 00004907 EBEC                <1> 	jmp	short sysexec_11
  2786                              <1> 	;
  2787                              <1> 	; 1:
  2788                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2789                              <1> 			     ; / pointers to arguments to be passed
  2790                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2791                              <1> 			      ; / u.quit = 1 take quit
  2792                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2793                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2794                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2795                              <1> 			       ; / system routine
  2796                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector
  2797                              <1> 			       ; / set to take system routine
  2798                              <1> 		; mov $sstack,sp / stack space used during swapping
  2799                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2800                              <1> 		; mov $ecore,r5 / r5 has end of core
  2801                              <1> 		; mov $core,r4 / r4 has start of users core
  2802                              <1> 		; mov r4,u.base / u.base has start of users core
  2803                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2804                              <1> 	; 1:
  2805                              <1> 		; tst (r2)+ / argument char = "nul"
  2806                              <1> 		; bne 1b
  2807                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of
  2808                              <1> 			  ; / end of argument pointer list
  2809                              <1> 	; 1:
  2810                              <1> 	     ; / move arguments to bottom of users core
  2811                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2812                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2813                              <1> 			    ; / ptr list
  2814                              <1> 		; blo 1f / branch to 1f when all arguments
  2815                              <1> 		       ; / are moved
  2816                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2817                              <1> 	; 2:
  2818                              <1> 		; tstb (r3)+
  2819                              <1> 		; bne 2b / scan argument for \0 (nul)
  2820                              <1> 
  2821                              <1> 	; 2:
  2822                              <1> 		; movb -(r3),-(r5) / move argument char 
  2823                              <1> 				 ; / by char starting at "ecore"
  2824                              <1> 		; cmp r3,(r2) / moved all characters in 
  2825                              <1> 			    ; / this argument
  2826                              <1> 		; bhi 2b / branch 2b if not
  2827                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2828                              <1> 			     ; / r5 has pointer to nth arg
  2829                              <1> 		; br 1b / string
  2830                              <1> 	; 1:
  2831                              <1> 		; clrb -(r5)
  2832                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2833                              <1> 			; / last word of argument strings
  2834                              <1> 		; mov $core,r2
  2835                              <1> 	
  2836                              <1> 	; 1: / move argument pointers into core following 
  2837                              <1> 	      ; / argument strings
  2838                              <1> 		; cmp r2,r4
  2839                              <1> 		; bhis 1f / branch to 1f when all pointers
  2840                              <1> 			; / are moved
  2841                              <1> 		; mov (r2)+,-(r5)
  2842                              <1> 		; br 1b
  2843                              <1> 	; 1:
  2844                              <1> 		; sub $core,r4 / gives number of arguments *2
  2845                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2846                              <1> 		       ; / the number of args stored
  2847                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2848                              <1> 			     ; / of the argument pointers
  2849                              <1> sysexec_13:
  2850                              <1> 	; 30/11/2021
  2851                              <1> 	; 28/11/2021
  2852                              <1> 	; 19/10/2015
  2853                              <1> 	; 18/10/2015
  2854                              <1> 	; 29/07/2015
  2855                              <1> 	; 25/07/2015
  2856                              <1> 	; 24/07/2015
  2857                              <1> 	; 20/07/2015
  2858                              <1> 	; 25/06/2015
  2859                              <1> 	; 24/06/2015
  2860                              <1> 	; 23/06/2015
  2861                              <1> 	;
  2862                              <1> 	; moving arguments to [ecore] is OK here..
  2863                              <1> 	; 18/10/2015
  2864 00004909 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2865                              <1> 	; ebx = beginning address of argument list pointers
  2866                              <1> 	;	in user's stack
  2867                              <1> 	; 19/10/2015
  2868 0000490B 2B1D[F4710000]      <1> 	sub 	ebx, [ecore]
  2869 00004911 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2870                              <1> 			; end of core - 4096 (last page)
  2871                              <1> 			; (virtual address)
  2872 00004917 891D[04720000]      <1> 	mov	[argv], ebx
  2873 0000491D 891D[68710000]      <1> 	mov	[u.break], ebx ; available user memory
  2874                              <1> 	;
  2875 00004923 29C0                <1> 	sub	eax, eax
  2876 00004925 C705[60710000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2876 0000492D 0000                <1>
  2877                              <1> 		; mov $14,u.count
  2878 0000492F C705[48710000]-     <1> 	mov	dword [u.fofp], u.off
  2878 00004935 [54710000]          <1>
  2879                              <1> 		; mov $u.off,u.fofp
  2880 00004939 A3[54710000]        <1> 	mov	[u.off], eax ; 0
  2881                              <1> 		; clr u.off / set offset in file to be read to zero
  2882                              <1> 	; 25/07/2015
  2883 0000493E A3[5C710000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2884                              <1> 	; 25/06/2015 
  2885 00004943 A1[10710000]        <1> 	mov	eax, [ii] ; 28/11/2021 (32 bit inode number)
  2886                              <1> 	; AX = i-number of the executable file
  2887 00004948 E8030F0000          <1> 	call	readi
  2888                              <1> 		; jsr r0,readi / read in first six words of 
  2889                              <1> 			; / user's file, starting at $core
  2890                              <1> 		; mov sp,r5 / put users stack address in r5
  2891                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2892                              <1> 				; / from r5 (leaves number of words
  2893                              <1> 				; / less 26 available for
  2894                              <1> 			     	; / program in user core
  2895                              <1> 		; mov r5,u.count /
  2896                              <1> 	; 25/06/2015
  2897 0000494D 8B0D[68710000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2898 00004953 890D[60710000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2899                              <1> 	;
  2900 00004959 8B0D[64710000]      <1> 	mov	ecx, [u.nread]
  2901 0000495F 890D[68710000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2902 00004965 80F920              <1> 	cmp	cl, 32
  2903 00004968 7540                <1>         jne     short sysexec_15
  2904                              <1> 	;:
  2905                              <1> 	; 25/06/2015
  2906                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2907                              <1> 	; 18/10/2015
  2908 0000496A 8B35[F0710000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2909                              <1> 		             ; (phys. start addr. of the exec. file)
  2910 00004970 AD                  <1> 	lodsd
  2911 00004971 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBh, 1Eh -> jump to +32
  2912 00004975 7533                <1> 	jne	short sysexec_15
  2913                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2914                              <1> 			      ; / if file is standard a.out format
  2915                              <1> 		; bne 1f / branch, if not standard format
  2916 00004977 AD                  <1> 	lodsd
  2917 00004978 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2918 0000497A AD                  <1> 	lodsd
  2919 0000497B 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2920                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2921                              <1> 		              ; / number of bytes in program text
  2922                              <1> 		; sub $14,r5 / subtract 12
  2923 0000497D 89CB                <1> 	mov	ebx, ecx
  2924                              <1> 	;
  2925                              <1> 	; 25/06/2015
  2926                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2927                              <1> 	;	and SINGLIX operating systems (as code template).
  2928                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2929                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2930                              <1> 	;	Overrun is not possible for current version.
  2931                              <1> 	;
  2932 0000497F AD                  <1> 	lodsd	
  2933 00004980 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2934 00004982 3B1D[60710000]      <1> 	cmp	ebx, [u.count]
  2935 00004988 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2936                              <1> 	;
  2937                              <1> 	; 24/07/2015
  2938                              <1> 	; add bss section size to [u.break]
  2939 0000498A 0105[68710000]      <1> 	add 	[u.break], eax
  2940                              <1> 	;
  2941 00004990 83E920              <1> 	sub	ecx, 32 ; header size (already loaded)
  2942                              <1> 	;cmp	ecx, [u.count]
  2943                              <1> 	;jnb	short sysexec_16
  2944                              <1> 		; cmp r5,u.count /
  2945                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2946 00004993 890D[60710000]      <1> 	mov	[u.count], ecx ; required read count
  2947                              <1> 		; mov r5,u.count
  2948                              <1> 	;
  2949 00004999 EB29                <1> 	jmp	short sysexec_16
  2950                              <1> 	;
  2951                              <1> sysexec_14:
  2952                              <1> 	; 23/06/2015
  2953                              <1> 	; insufficient (out of) memory
  2954 0000499B C705[AC710000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2954 000049A3 0000                <1>
  2955 000049A5 E91DF3FFFF          <1> 	jmp	error
  2956                              <1> 	;
  2957                              <1> sysexec_15:
  2958                              <1> 	; 25/06/2015
  2959                              <1>         ;movzx   edx, word [i.size] ; file size
  2960                              <1> 	; 30/11/2021
  2961 000049AA 8B15[D86D0000]      <1> 	mov	edx, [i.size] ; file size
  2962 000049B0 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2963 000049B2 7626                <1> 	jna	short sysexec_17 ; no need to next read
  2964 000049B4 01D1                <1> 	add	ecx, edx ; [i.size]
  2965 000049B6 3B0D[60710000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2966 000049BC 77DD                <1> 	ja	short sysexec_14
  2967 000049BE 8915[60710000]      <1> 	mov	[u.count], edx
  2968                              <1> sysexec_16:
  2969                              <1> 	;mov	ax, [ii] ; i-number
  2970                              <1> 	; 28/11/2021
  2971 000049C4 A1[10710000]        <1> 	mov	eax, [ii] ; 32 bit inode number
  2972 000049C9 E8820E0000          <1> 	call	readi
  2973                              <1> 		; add core+10,u.nread / add size of user data area
  2974                              <1> 		                    ; / to u.nread
  2975                              <1> 		; br 2f
  2976                              <1> 	; 1:
  2977                              <1> 		; jsr r0,readi / read in rest of file
  2978                              <1> 	; 2:
  2979 000049CE 8B0D[64710000]      <1> 	mov	ecx, [u.nread]
  2980 000049D4 010D[68710000]      <1> 	add	[u.break], ecx
  2981                              <1> 		; mov u.nread,u.break / set users program break to end of
  2982                              <1> 				    ; / user code
  2983                              <1> 		; add $core+14,u.break / plus data area
  2984                              <1> 	; 20/07/2015
  2985                              <1> sysexec_17:
  2986                              <1> 	; 26/03/2021 - Retro UNIX 386 v2
  2987                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2988                              <1> 	;;mov	ax, [ii] ; i-number
  2989                              <1> 	;call	iclose
  2990                              <1> 	;	; jsr r0,iclose / does nothing
  2991 000049DA 31C0                <1>         xor     eax, eax
  2992 000049DC FEC0                <1> 	inc	al
  2993 000049DE 66A3[84710000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  2994 000049E4 66A3[86710000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  2995                              <1> 	; 30/11/2021
  2996 000049EA FEC8                <1> 	dec	al  ; eax = 0
  2997                              <1> 	; 02/07/2015
  2998                              <1>         ;cmp	dword [u.ppgdir], 0 ; is the caller sys_init (kernel) ?
  2999 000049EC 3905[9C710000]      <1> 	cmp	[u.ppgdir], eax ; 0 ; is the caller sys_init (kernel) ?
  3000 000049F2 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3001                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3002 000049F4 8B15[38700000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3003 000049FA 8915[9C710000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here
  3004                              <1> sysexec_18:
  3005                              <1> 
  3006                              <1> ; temporary - 28/11/2021
  3007                              <1> ;mov	dword [0B8004h], 4E394E39h
  3008                              <1> ;mov	ecx, 0FFFFh
  3009                              <1> ;above7:
  3010                              <1> ;dec	edx
  3011                              <1> ;inc	edx
  3012                              <1> ;loop	above7
  3013                              <1> 
  3014                              <1> ;; temporary - 04/12/2021
  3015                              <1> ;;push	eax
  3016                              <1> ;mov	esi, [pcore]
  3017                              <1> ;add	esi, 0AFh
  3018                              <1> ;call	print_msg
  3019                              <1> ;pop	eax
  3020                              <1> ;mov	ecx, 0FFFFh
  3021                              <1> ;above8:
  3022                              <1> ;dec	edx
  3023                              <1> ;inc	edx
  3024                              <1> ;loop	above8
  3025                              <1> 
  3026                              <1> 	; 18/10/2015
  3027                              <1> 	; 05/08/2015
  3028                              <1> 	; 29/07/2015
  3029 00004A00 8B2D[04720000]      <1> 	mov	ebp, [argv] ; user's stack pointer must points to argument
  3030                              <1> 			    ; list pointers (argument count)
  3031 00004A06 FA                  <1> 	cli
  3032 00004A07 8B25[D46F0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3033                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3034                              <1> 			    ; for this process	 
  3035                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3036                              <1> 	;;xor	eax, eax ; 0
  3037                              <1> 	;dec	al ; eax = 0
  3038                              <1> 	; eax = 0 ; 30/11/2021 
  3039 00004A0D 66BA2300            <1> 	mov	dx, UDATA
  3040 00004A11 6652                <1> 	push	dx  ; user's stack segment
  3041 00004A13 55                  <1> 	push	ebp ; user's stack pointer
  3042                              <1> 		    ; (points to number of arguments)
  3043 00004A14 FB                  <1> 	sti
  3044 00004A15 9C                  <1> 	pushfd	; EFLAGS
  3045                              <1> 		; Set IF for enabling interrupts in user mode
  3046                              <1> 	;or	dword [esp], 200h 
  3047                              <1> 	;
  3048                              <1> 	;mov	bx, UCODE
  3049                              <1> 	;push	bx ; user's code segment
  3050 00004A16 6A1B                <1> 	push	UCODE
  3051                              <1> 	;push	0
  3052 00004A18 50                  <1> 	push	eax ; EIP (=0) - start address -
  3053                              <1> 		; clr -(r5) / popped into ps when rti in 
  3054                              <1> 			  ; / sysrele is executed
  3055                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3056                              <1> 		                ; / in sysrele is executed
  3057                              <1> 		;mov r5,0f / load second copyz argument
  3058                              <1> 		;tst -(r5) / decrement r5
  3059 00004A19 8925[2C710000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3060                              <1> 	; 05/08/2015
  3061                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3062                              <1> 	; ('push dx' would cause to general protection fault, 
  3063                              <1> 	; after 'pop ds' etc.)
  3064                              <1> 	;
  3065                              <1> 	;; push dx ; ds (UDATA)
  3066                              <1> 	;; push dx ; es (UDATA)
  3067                              <1> 	;; push dx ; fs (UDATA)
  3068                              <1> 	;; push dx ; gs (UDATA)
  3069                              <1> 	;
  3070                              <1> 	; This is a trick to prevent general protection fault
  3071                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3072 00004A1F 8EC2                <1> 	mov 	es, dx ; UDATA
  3073 00004A21 06                  <1> 	push 	es ; ds (UDATA)
  3074 00004A22 06                  <1> 	push 	es ; es (UDATA)
  3075 00004A23 06                  <1> 	push 	es ; fs (UDATA)
  3076 00004A24 06                  <1> 	push	es ; gs (UDATA)
  3077 00004A25 66BA1000            <1> 	mov	dx, KDATA
  3078 00004A29 8EC2                <1> 	mov	es, dx
  3079                              <1> 	;
  3080                              <1> 	;; pushad simulation
  3081 00004A2B 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3082 00004A2D 50                  <1> 	push	eax ; eax (0)
  3083 00004A2E 50                  <1> 	push	eax ; ecx (0)
  3084 00004A2F 50                  <1> 	push	eax ; edx (0)
  3085 00004A30 50                  <1> 	push	eax ; ebx (0)
  3086 00004A31 55                  <1> 	push	ebp ; esp before pushad
  3087 00004A32 50                  <1> 	push	eax ; ebp (0)
  3088 00004A33 50                  <1> 	push	eax ; esi (0)		
  3089 00004A34 50                  <1> 	push	eax ; edi (0)	
  3090                              <1> 	;
  3091 00004A35 A3[34710000]        <1> 	mov	[u.r0], eax ; eax = 0
  3092 00004A3A 8925[30710000]      <1> 	mov	[u.usp], esp
  3093                              <1> 		; mov r5,u.r0 /
  3094                              <1> 		; sub $16.,r5 / skip 8 words
  3095                              <1> 		; mov r5,u.sp / assign user stack pointer value,
  3096                              <1> 		;             / effectively zeroes all regs
  3097                              <1> 			    ; / when sysrele is executed
  3098                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3099                              <1> 		; clr u.break
  3100                              <1> 		; mov r5,sp / point sp to user's stack
  3101                              <1> 	;
  3102 00004A40 E9A4F2FFFF          <1> 	jmp	sysret0
  3103                              <1> 	;jmp	sysret
  3104                              <1> 		; br sysret3 / return to core image at $core
  3105                              <1> 
  3106                              <1> get_argp:
  3107                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  3108                              <1> 	; 18/10/2015 (nbase, ncount)
  3109                              <1> 	; 21/07/2015
  3110                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3111                              <1> 	; Get (virtual) address of argument from user's core memory
  3112                              <1> 	;
  3113                              <1> 	; INPUT:
  3114                              <1> 	;	esi = virtual address of argument pointer
  3115                              <1> 	; OUTPUT:
  3116                              <1> 	;	eax = virtual address of argument
  3117                              <1> 	;
  3118                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3119                              <1> 	;
  3120 00004A45 833D[9C710000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3121                              <1> 				    ; (the caller is kernel)
  3122 00004A4C 767C                <1>         jna     short get_argpk 
  3123                              <1> 	;
  3124 00004A4E 89F3                <1>      	mov	ebx, esi
  3125 00004A50 E807E9FFFF          <1> 	call	get_physical_addr ; get physical address
  3126 00004A55 7254                <1>         jc	short get_argp_err ; 11/12/2021
  3127 00004A57 A3[F8710000]        <1> 	mov 	[nbase], eax ; physical address	
  3128                              <1> 	;mov	[ncount], cx ; remain byte count in page (1-4096)
  3129                              <1> 	; 11/12/2021
  3130 00004A5C 890D[FC710000]      <1> 	mov	[ncount], ecx
  3131 00004A62 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3132                              <1> 	;cmp	cx, ax ; 4
  3133                              <1> 	; 11/12/2021
  3134 00004A67 39C1                <1> 	cmp	ecx, eax ; 4
  3135 00004A69 734A                <1> 	jnb	short get_argp2
  3136 00004A6B 89F3                <1> 	mov	ebx, esi
  3137 00004A6D 01CB                <1> 	add	ebx, ecx
  3138 00004A6F E8E8E8FFFF          <1> 	call	get_physical_addr ; get physical address
  3139 00004A74 7235                <1> 	jc	short get_argp_err
  3140                              <1> 	;push	esi
  3141 00004A76 89C6                <1> 	mov	esi, eax
  3142                              <1> 	;xchg	cx, [ncount]
  3143                              <1> 	; 11/12/2021
  3144 00004A78 870D[FC710000]      <1> 	xchg	ecx, [ncount]
  3145 00004A7E 8735[F8710000]      <1> 	xchg	esi, [nbase]
  3146 00004A84 B504                <1> 	mov	ch, 4
  3147 00004A86 28CD                <1> 	sub	ch, cl
  3148                              <1> get_argp0:
  3149 00004A88 AC                  <1> 	lodsb
  3150                              <1> 	;push	ax
  3151                              <1> 	; 11/12/2021
  3152 00004A89 50                  <1> 	push	eax
  3153 00004A8A FEC9                <1> 	dec	cl
  3154 00004A8C 75FA                <1>         jnz     short get_argp0
  3155 00004A8E 8B35[F8710000]      <1> 	mov	esi, [nbase]
  3156                              <1> 	; 21/07/2015
  3157 00004A94 0FB6C5              <1> 	movzx	eax, ch
  3158 00004A97 0105[F8710000]      <1> 	add	[nbase], eax
  3159                              <1> 	;sub	[ncount], ax
  3160                              <1> 	; 11/12/2021
  3161 00004A9D 2905[FC710000]      <1> 	sub	[ncount], eax
  3162                              <1> get_argp1:
  3163 00004AA3 AC                  <1> 	lodsb
  3164 00004AA4 FECD                <1> 	dec	ch
  3165 00004AA6 743B                <1>         jz      short get_argp3
  3166                              <1>         ;push	ax
  3167                              <1> 	; 11/12/2021
  3168 00004AA8 50                  <1> 	push	eax
  3169 00004AA9 EBF8                <1> 	jmp     short get_argp1
  3170                              <1> get_argp_err:
  3171 00004AAB A3[AC710000]        <1> 	mov	[u.error], eax
  3172 00004AB0 E912F2FFFF          <1> 	jmp	error
  3173                              <1> get_argp2:
  3174                              <1> 	; 21/07/2015
  3175                              <1> 	;mov	eax, 4
  3176 00004AB5 8B15[F8710000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3177 00004ABB 0105[F8710000]      <1> 	add	[nbase], eax
  3178                              <1> 	;sub	[ncount], ax
  3179                              <1> 	; 11/12/2021
  3180 00004AC1 2905[FC710000]      <1> 	sub	[ncount], eax
  3181                              <1> 	;
  3182 00004AC7 8B02                <1> 	mov	eax, [edx]
  3183 00004AC9 C3                  <1> 	retn
  3184                              <1> get_argpk:
  3185                              <1> 	; Argument is in kernel's memory space
  3186 00004ACA 66C705[FC710000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3186 00004AD2 10                  <1>
  3187 00004AD3 8935[F8710000]      <1> 	mov	[nbase], esi
  3188 00004AD9 8305[F8710000]04    <1> 	add	dword [nbase], 4
  3189 00004AE0 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physical addr.
  3190 00004AE2 C3                  <1> 	retn
  3191                              <1> get_argp3:
  3192 00004AE3 B103                <1> 	mov	cl, 3
  3193                              <1> get_argp4:
  3194 00004AE5 C1E008              <1> 	shl	eax, 8
  3195                              <1> 	;pop	dx
  3196                              <1> 	; 11/12/2021
  3197 00004AE8 5A                  <1> 	pop	edx
  3198 00004AE9 88D0                <1> 	mov 	al, dl
  3199 00004AEB E2F8                <1>         loop    get_argp4
  3200                              <1> 	;pop	esi
  3201 00004AED C3                  <1> 	retn	
  3202                              <1> 
  3203                              <1> sysfstat: 
  3204                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3205                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3206                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3207                              <1> 	;
  3208                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3209                              <1> 	; on open files instead of files given by name. It puts the
  3210                              <1> 	; buffer address on the stack, gets the i-number and
  3211                              <1> 	; checks to see if the file is open for reading or writing.
  3212                              <1> 	; If the file is open for writing (i-number is negative)
  3213                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3214                              <1> 	; is made.	
  3215                              <1> 	;
  3216                              <1> 	; Calling sequence:
  3217                              <1> 	;	sysfstat; buf
  3218                              <1> 	; Arguments:
  3219                              <1> 	;	buf - buffer address
  3220                              <1> 	;
  3221                              <1> 	; Inputs: *u.r0 - file descriptor
  3222                              <1> 	; Outputs: buffer is loaded with file information
  3223                              <1> 	; ...............................................................
  3224                              <1> 	;				
  3225                              <1> 	; Retro UNIX 8086 v1 modification:
  3226                              <1> 	;       'sysfstat' system call has two arguments; so,
  3227                              <1> 	;	* 1st argument, file descriptor is in BX register
  3228                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3229                              <1> 
  3230                              <1> 	; / set status of open file
  3231                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3232 00004AEE 51                  <1> 	push	ecx ; *
  3233                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3234                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3235                              <1> 		; jsr r0,getf / get the files i-number
  3236                              <1> 	; BX = file descriptor (file number)
  3237 00004AEF E8F5000000          <1> 	call	getf1
  3238 00004AF4 6621C0              <1> 	and	ax, ax ; i-number of the file
  3239                              <1> 		; tst	r1 / is it 0?
  3240                              <1> 	;jz	error
  3241                              <1> 		; beq error3 / yes, error
  3242                              <1> 	;jnz	short sysfstat1
  3243                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2 (runix v2 file system)
  3244 00004AF7 752F                <1> 	jnz	short sysstat1
  3245 00004AF9 C705[AC710000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3245 00004B01 0000                <1>
  3246 00004B03 E9BFF1FFFF          <1> 	jmp	error
  3247                              <1> 	; 26/12/2021
  3248                              <1> ;sysfstat1:
  3249                              <1> 	;cmp	ah, 80h
  3250                              <1>         ;jb      short sysstat1
  3251                              <1> 	;	; bgt 1f / if i-number is negative (open for writing)
  3252                              <1> 	;neg	ax
  3253                              <1> 	;	; neg r1 / make it positive, then branch
  3254 00004B08 EB1E                <1> 	jmp	short sysstat1
  3255                              <1> 		; br 1f / to 1f
  3256                              <1> sysstat:
  3257                              <1> 	; 26/12/2021 (Retro UNIX 386 v1.2) 
  3258                              <1> 	; 18/10/2015
  3259                              <1> 	; 07/10/2015
  3260                              <1> 	; 02/09/2015
  3261                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3262                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3263                              <1> 	;
  3264                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3265                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3266                              <1> 	; long and information about the file placed in it.	
  3267                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3268                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3269                              <1> 	; is then loaded and the results are given in the UNIX
  3270                              <1> 	; Programmers Manual sysstat (II).	
  3271                              <1> 	;
  3272                              <1> 	; Calling sequence:
  3273                              <1> 	;	sysstat; name; buf
  3274                              <1> 	; Arguments:
  3275                              <1> 	;	name - points to the name of the file
  3276                              <1> 	;	buf - address of a 34 bytes buffer
  3277                              <1> 	; Inputs: -
  3278                              <1> 	; Outputs: buffer is loaded with file information
  3279                              <1> 	; ...............................................................
  3280                              <1> 	;				
  3281                              <1> 	; Retro UNIX 8086 v1 modification: 
  3282                              <1> 	;       'sysstat' system call has two arguments; so,
  3283                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3284                              <1> 	;	to get sysstat system call arguments from the user;
  3285                              <1> 	;	* 1st argument, name is pointed to by BX register
  3286                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3287                              <1> 	;
  3288                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3289                              <1> 	;	      arguments which were in these registers;
  3290                              <1> 	;	      but, it returns by putting the 1st argument
  3291                              <1> 	;	      in 'u.namep' and the 2nd argument
  3292                              <1> 	;	      on top of stack. (1st argument is offset of the
  3293                              <1> 	;	      file/path name in the user's program segment.)		 	
  3294                              <1> 	
  3295                              <1> 	; / ; name of file; buffer - get files status
  3296                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3297 00004B0A 891D[50710000]      <1> 	mov	[u.namep], ebx
  3298 00004B10 51                  <1> 	push	ecx ; *
  3299 00004B11 E83E010000          <1> 	call	namei
  3300                              <1> 		; jsr r0,namei / get the i-number for the file
  3301                              <1> 	;jc	error
  3302                              <1> 		; br error3 / no such file, error
  3303 00004B16 7310                <1> 	jnc	short sysstat1
  3304                              <1> 	; pop 	ecx
  3305                              <1> sysstat_err0:
  3306                              <1> 	; 'file not found !' error
  3307 00004B18 C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3307 00004B20 0000                <1>
  3308 00004B22 E9A0F1FFFF          <1> 	jmp	error
  3309                              <1> 
  3310 00004B27 00                  <1> statx: db 0
  3311                              <1> 
  3312                              <1> sysstat1: ; 1:
  3313 00004B28 E8BA0A0000          <1> 	call	iget
  3314                              <1> 		; jsr r0,iget / get the i-node into core
  3315                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3316                              <1> 	; 02/09/2015
  3317 00004B2D 8F05[5C710000]      <1> 	pop	dword [u.base] ; *
  3318                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3319 00004B33 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3320 00004B38 730A                <1> 	jnc 	short sysstat2
  3321                              <1> sysstat_err1:
  3322 00004B3A A3[AC710000]        <1> 	mov	dword [u.error], eax ; error code
  3323 00004B3F E983F1FFFF          <1> 	jmp	error
  3324                              <1> sysstat2:
  3325 00004B44 A0[10710000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3326 00004B49 AA                  <1> 	stosb
  3327 00004B4A FF05[5C710000]      <1> 	inc 	dword [u.base]
  3328                              <1> 	;dec 	cx
  3329 00004B50 49                  <1> 	dec	ecx ; 26/12/2021
  3330 00004B51 7505                <1> 	jnz	short sysstat3
  3331 00004B53 E835000000          <1> 	call	sysstat_gpa
  3332                              <1> 	;jc	short sysstat_err1
  3333                              <1> sysstat3:
  3334 00004B58 A0[11710000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3335 00004B5D AA                  <1> 	stosb
  3336                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3337 00004B5E FF05[5C710000]      <1> 	inc 	dword [u.base]
  3338                              <1> 	;;dec 	word [u.pcount]
  3339                              <1> 	;dec	cx
  3340 00004B64 49                  <1> 	dec	ecx ; 26/12/2021
  3341 00004B65 7505                <1> 	jnz	short sysstat4
  3342 00004B67 E821000000          <1> 	call	sysstat_gpa
  3343                              <1> 	;jc	short sysstat_err1	
  3344                              <1> sysstat4:
  3345 00004B6C BE[D06D0000]        <1> 	mov	esi, inode
  3346                              <1> 		; mov $inode,r2 / r2 points to i-node
  3347                              <1> sysstat5: ; 1:
  3348 00004B71 A4                  <1> 	movsb
  3349                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3350 00004B72 FF05[5C710000]      <1> 	inc 	dword [u.base]
  3351                              <1> 	;;dec 	word [u.pcount]
  3352                              <1> 	;dec	cx
  3353 00004B78 49                  <1> 	dec	ecx ; 26/12/2021
  3354 00004B79 7505                <1> 	jnz	short sysstat6
  3355 00004B7B E80D000000          <1> 	call	sysstat_gpa
  3356                              <1> 	;jc	short sysstat_err1
  3357                              <1> sysstat6:
  3358                              <1> 	; 26/12/2021 - Retro UNIX 386 v1.2
  3359 00004B80 81FE[106E0000]      <1> 	cmp	esi, inode + 64 ; Retro UNIX v2 inode		
  3360                              <1> 	;cmp	esi, inode + 32
  3361                              <1> 		; cmp r2,$inode+32 / done?
  3362 00004B86 75E9                <1> 	jne	short sysstat5
  3363                              <1> 		; bne 1b / no, go back
  3364 00004B88 E95AF1FFFF          <1> 	jmp	sysret
  3365                              <1> 		; br sysret3 / return through sysret
  3366                              <1> 	;
  3367                              <1> sysstat_gpa: ; get physical address of file status buffer
  3368                              <1> 	; 02/09/2015
  3369 00004B8D 8B1D[5C710000]      <1> 	mov 	ebx, [u.base]
  3370                              <1> 	; 07/10/2015
  3371 00004B93 E8C4E7FFFF          <1> 	call	get_physical_addr ; get physical address
  3372                              <1> 	;jc	short sysstat_gpa1
  3373 00004B98 72A0                <1> 	jc	short sysstat_err1
  3374                              <1> 	; 18/10/2015
  3375 00004B9A 89C7                <1> 	mov	edi, eax ; physical address
  3376                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3377                              <1> ;sysstat_gpa1:
  3378 00004B9C C3                  <1> 	retn
  3379                              <1> 
  3380                              <1> fclose:
  3381                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3382                              <1> 	; 08/04/2021
  3383                              <1> 	; 04/04/2021
  3384                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3385                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3386                              <1> 	;            (32 bit offset pointer modification)
  3387                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3388                              <1> 	;
  3389                              <1> 	; Given the file descriptor (index to the u.fp list)
  3390                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3391                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3392                              <1> 	; u.fp list is cleared. If all the processes that opened
  3393                              <1> 	; that file close it, then fsp etry is freed and the file
  3394                              <1> 	; is closed. If not a return is taken. 
  3395                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3396                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3397                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3398                              <1> 	; a check is made to see if the file is special.	
  3399                              <1> 	;
  3400                              <1> 	; INPUTS ->
  3401                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3402                              <1> 	;    u.fp - list of entries in the fsp table
  3403                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3404                              <1> 	; OUTPUTS ->
  3405                              <1> 	;    r1 - contains the same file descriptor
  3406                              <1> 	;    r2 - contains i-number
  3407                              <1> 	;
  3408                              <1> 	; ((AX = R1))
  3409                              <1> 	; ((Modified registers: edx, ebx, ecx, esi, edi, ebp))
  3410                              <1> 	;
  3411                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3412                              <1> 	;              if i-number of the file is 0. (error)
  3413                              <1> 
  3414                              <1> 	; 08/04/2021
  3415                              <1> 	; INPUT:
  3416                              <1> 	;	eax = file descriptor
  3417                              <1> 	; OUTPUT:
  3418                              <1> 	;	cf = 0 -> eax = file descriptor
  3419                              <1> 	;	cf = 1 -> eax = error code
  3420                              <1> 	;		  (al = 0 -> file not open)
  3421                              <1> 
  3422                              <1> 	; 18/08/2020
  3423                              <1> 	;movzx	edx, ax ; **
  3424 00004B9D 89C3                <1> 	mov	ebx, eax
  3425                              <1> 
  3426                              <1> 	; 18/08/2020
  3427                              <1> _fclose:
  3428 00004B9F 53                  <1> 	push	ebx ; ***  ; file descriptor (index to u.fp)
  3429                              <1> 
  3430                              <1> 	;push	ax ; ***
  3431                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3432                              <1> 			     ; / the index to u.fp list)
  3433                              <1> 	; ebx = file descriptor/number
  3434 00004BA0 E844000000          <1> 	call	getf
  3435                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3436                              <1> 			    ; / cdev has device =, u.fofp 
  3437                              <1> 			    ; / points to 3rd word of fsp entry
  3438                              <1> 	;cmp	eax, 1 ; 18/08/2020
  3439 00004BA5 6683F801            <1> 	cmp	ax, 1 ; r1
  3440                              <1> 		; tst r1 / is i-number 0?
  3441 00004BA9 723C                <1> 	jb	short fclose_2
  3442                              <1> 		; beq 1f / yes, i-node not active so return
  3443                              <1> 		; tst (r0)+ / no, jump over error return
  3444                              <1> 	
  3445                              <1> 	;mov	ebx, edx ; **
  3446                              <1>  	; 18/08/2020
  3447 00004BAB 8B1C24              <1> 	mov	ebx, [esp]
  3448                              <1> 	;mov	edx, eax 
  3449                              <1> 	;;mov 	dx, ax ; *
  3450                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3451                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3452                              <1> 			    ; / which is index to u.fp ; **
  3453 00004BAE C683[3E710000]00    <1> 	mov	byte [ebx+u.fp], 0
  3454                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3455 00004BB5 8B1D[48710000]      <1> 	mov	ebx, [u.fofp]
  3456                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3457                              <1> 
  3458                              <1> 	; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3459                              <1> 	; ebx = 5th word of fsp entry (64 bit file offset)
  3460                              <1> fclose_0:
  3461                              <1> 	;;dec	byte [ebx-2] ; 18/08/2020 - Retro UNIX 386 v2
  3462                              <1> 	; 04/04/2021
  3463 00004BBB FE4BFF              <1> 	dec	byte [ebx-1] ; 04/04/2021 - Retro UNIX 386 v2
  3464                              <1> 	;dec	byte [ebx+4] ; 18/06/2015
  3465                              <1> 		; decb 2(r1) / decrement the number of processes 
  3466                              <1> 			   ; / that have opened the file
  3467 00004BBE 7927                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3468                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3469                              <1> 	;
  3470                              <1> 	;push	dx ; *
  3471                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3472                              <1> 	;;xor	ax, ax ; 0
  3473                              <1> 	;xor	eax, eax ; 18/08/2020
  3474                              <1> 		; clear 1st word of fsp entry
  3475                              <1> 	;mov	[ebx-8], ax ; 0 ; 18/08/2020
  3476                              <1> 	; 18/08/2020 - Retro UNIX 386 v2
  3477 00004BC0 66C743F80000        <1> 	mov	word [ebx-8], 0 ; clear 1st word of fsp entry ; i-number
  3478                              <1> 			; Note: 32 bit i-node number field is ready but
  3479                              <1> 			;	it is not used in current runix version.	
  3480                              <1> 
  3481                              <1> 	;;mov	[ebx-4], ax ; 0
  3482                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3483                              <1> 	;mov	al, [ebx+5] ; 18/06/2015
  3484                              <1> 	;	; tstb	3(r1) / has this file been deleted
  3485                              <1> 	;and	al, al
  3486                              <1> 	;jz	short fclose_1
  3487                              <1> 	;	; beq 2f / no, branch
  3488                              <1> 
  3489                              <1> 	;push	edx ; * ; 18/08/2020
  3490                              <1> 	;mov	eax, edx ; * ; 18/08/2020
  3491                              <1> 
  3492                              <1> 	;; 18/08/2020 - Retro UNIX 386 v2 (new fsp structure)
  3493                              <1> 	;;test	byte [ebx-3], 80h ; open mode & status flags
  3494                              <1> 	; 04/04/2021 - Retro UNIX 386 v2 (new fsp structure)
  3495                              <1> 	;test	byte [ebx-4], 80h ; open mode & status flags 
  3496                              <1> 	;jz	short fclose_1	; deleted file flag (bit 7)
  3497                              <1> 
  3498                              <1> 	; 04/04/2021
  3499 00004BC6 31D2                <1> 	xor	edx, edx
  3500 00004BC8 8A53FC              <1> 	mov	dl, [ebx-4] ; open mode & status flags
  3501 00004BCB F6C280              <1> 	test	dl, 80h	    ; deleted file flag (bit 7)
  3502 00004BCE 7409                <1> 	jz	short fclose_1 ; (not deleted -while open-)
  3503 00004BD0 52                  <1> 	push	edx
  3504                              <1> 
  3505                              <1> 	; deleted file !
  3506                              <1> 
  3507                              <1> 	;mov	ax, dx ; *
  3508                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3509                              <1> 	; AX = inode number
  3510 00004BD1 E89E040000          <1> 	call	anyi
  3511                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3512                              <1> 			    ; / check if file appears in fsp again
  3513                              <1> 	; 04/04/2021
  3514 00004BD6 5A                  <1> 	pop	edx
  3515                              <1> 	; 08/04/2021
  3516 00004BD7 720C                <1> 	jc	short fclose_3 ; error code in eax	
  3517                              <1> 	; 18/08/2020
  3518                              <1> 	; jmp short fclose_2
  3519                              <1> 
  3520                              <1> 	; ax = inode number
  3521                              <1> fclose_1: ; 2:
  3522                              <1> 	; 04/04/2021
  3523 00004BD9 80E201              <1> 	and	dl, 1
  3524 00004BDC FEC2                <1> 	inc	dl ; 0 -> 1 (open for read), 1 -> 2 (open for write)
  3525                              <1> 	
  3526                              <1> 	;pop	eax ; * ; 18/08/2020 
  3527                              <1> 	;;pop	ax ; *
  3528                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3529 00004BDE E89F130000          <1> 	call	iclose ; close if it is special file 
  3530                              <1> 		; jsr r0,iclose / check to see if it is a special file
  3531                              <1> 	; 08/04/2021
  3532 00004BE3 7302                <1> 	jnc	short fclose_2
  3533                              <1> fclose_3:
  3534 00004BE5 5B                  <1> 	pop	ebx  ; ***  ; file descriptor
  3535                              <1> 	; eax = error code
  3536 00004BE6 C3                  <1> 	retn
  3537                              <1> fclose_2: ; 1:
  3538 00004BE7 58                  <1> 	pop	eax ; *** ; 18/08/2020
  3539                              <1> 	;pop	ax ; ***
  3540                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3541 00004BE8 C3                  <1> 	retn
  3542                              <1> 		; rts r0
  3543                              <1> 
  3544                              <1> 	; 04/12/2021 - Retro UNIX 386 v2 fs compatibility code
  3545                              <1> getf:	; / get the device number and the i-number of an open file
  3546                              <1> 	; 13/05/2015
  3547                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3548                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3549                              <1> 
  3550                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  3551                              <1> 	;
  3552                              <1> 	; 16/05/2021
  3553                              <1> 	; 27/03/2020 - Retro UNIX 386 v2 
  3554                              <1> 	;	(new open files -fsp- structure)
  3555                              <1> 	; 13/05/2015
  3556                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3557                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3558                              <1> 	
  3559                              <1> 	; INPUT: 
  3560                              <1> 	;    ;eax = file descriptor/number
  3561                              <1> 	;     ebx = file descriptor/number ; 18/08/2020 	
  3562                              <1> 	; OUTPUT:
  3563                              <1> 	;     bl = open mode & status flag ; 27/03/2020
  3564                              <1> 	;        (bit 0 open mode flag, 0 = read, 1 = write)  
  3565                              <1> 	;    eax = inode number (in AX)
  3566                              <1> 	;          If eax = 0 -> file not open
  3567                              <1> 	;   byte [cdev] = logical drive number (of inode in eax)
  3568                              <1> 	;	
  3569                              <1> 	; Modified registers: eax, ebx
  3570                              <1> 
  3571                              <1> 	; 16/05/2021 ('getf' procedure, unix v7 x86 'fio.c')
  3572                              <1> 	; /*
  3573                              <1> 	;  * Convert a user supplied
  3574                              <1> 	;  * file descriptor into a pointer
  3575                              <1> 	;  * to a file structure.
  3576                              <1> 	;  * Only task is to check range
  3577                              <1> 	;  * of the descriptor.
  3578                              <1> 	;  */
  3579                              <1> 	; struct file *
  3580                              <1> 	; getf(f)
  3581                              <1> 	;
  3582                              <1> 	; 18/08/2020
  3583                              <1> 	; 	ebx = file descriptor/number
  3584                              <1> 
  3585                              <1> 	; 16/05/2021
  3586                              <1> 	NOFILE	equ 10
  3587                              <1> 
  3588                              <1> 	; 18/08/2020
  3589                              <1> 	;mov	ebx, eax
  3590                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3591                              <1> 
  3592                              <1> 	; ebx = file descriptor/number
  3593                              <1> 
  3594                              <1> 	; 18/08/2020
  3595 00004BE9 29C0                <1> 	sub	eax, eax ; eax = 0
  3596                              <1>  
  3597 00004BEB 83FB0A              <1> 	cmp	ebx, 10 ; cmp ebx, NOFILE ; 16/05/2021
  3598                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3599 00004BEE 7363                <1>         jnb	short getf2 ; 13/05/2015
  3600                              <1> 	;jnb	error
  3601                              <1> 		; bhis error3 / u.fp is table of users open files,
  3602                              <1> 			    ; / index in fsp table
  3603 00004BF0 8A9B[3E710000]      <1> 	mov	bl, [ebx+u.fp]
  3604                              <1> 		; movb u.fp(r1),r1 / r1 contains number of entry 
  3605                              <1> 		                 ; / in fsp table
  3606 00004BF6 08DB                <1> 	or	bl, bl
  3607                              <1> 	;jnz	short getf3
  3608 00004BF8 7459                <1> 	jz	short getf2 ; 18/08/2020
  3609                              <1> 	;;jz	short getf4
  3610                              <1> 		; beq 1f / if its zero return
  3611                              <1> ;getf2:
  3612                              <1> ;	; 'File not open !' error (ax=0)
  3613                              <1> ;	;sub	eax, eax ; 18/08/2020
  3614                              <1> ;	retn
  3615                              <1> ;getf3:	
  3616                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3617                              <1> 	;
  3618                              <1> 	; 'fsp' table (10 bytes/entry)
  3619                              <1> 	; bit 15				   bit 0
  3620                              <1> 	; ---|-------------------------------------------
  3621                              <1> 	; r/w|		i-number of open file
  3622                              <1> 	; ---|-------------------------------------------
  3623                              <1> 	;		   device number
  3624                              <1> 	; -----------------------------------------------
  3625                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3626                              <1> 	; -----------------------------------------------
  3627                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3628                              <1> 	; ----------------------|------------------------
  3629                              <1> 	;  flag that says file 	| number of processes
  3630                              <1> 	;   has been deleted	| that have file open 
  3631                              <1> 	; ----------------------|------------------------
  3632                              <1> 
  3633                              <1> 	; Retro UNIX 386 v2 modification ! (27/03/2020)
  3634                              <1> 
  3635                              <1> 	; bit 15 				    bit 0
  3636                              <1> 	; ----------------------------------------------- byte 0
  3637                              <1> 	;    	       i-number of open file           
  3638                              <1> 	; ----------------------------------------------- byte 2
  3639                              <1> 	;          high word of 32 bit i-number       
  3640                              <1> 	; ----------------------------------------------- byte 4
  3641                              <1> 	;    open mode & status  |   device number     
  3642                              <1> 	; ----------------------------------------------- byte 6
  3643                              <1> 	;       reserved byte    |    open count  
  3644                              <1> 	; ----------------------------------------------- byte 8
  3645                              <1> 	;   offset pointer, i.e., r/w pointer to file 
  3646                              <1> 	; ----------------------------------------------- byte 10
  3647                              <1> 	;     64 bit file offset pointer (bit 16-31)  
  3648                              <1> 	; ----------------------------------------------- byte 12
  3649                              <1> 	;     64 bit file offset pointer (bit 32-47)   
  3650                              <1> 	; ----------------------------------------------- byte 14
  3651                              <1> 	;     64 bit file offset pointer (bit 48-63)  
  3652                              <1> 	; ----------------------------------------------- byte 16
  3653                              <1> 	
  3654                              <1> 	; 11/05/2015 - Retro UNIX 386 v1
  3655                              <1> 	;mov	eax, 10
  3656                              <1> 
  3657                              <1> 	; 27/03/2020 - Retro UNIX 386 v2	
  3658                              <1> 	;mov	eax, opfls.size ; mov eax, 16
  3659                              <1> 	
  3660                              <1> 	;sub	eax, eax ; 18/08/2020 ; eax = 0
  3661                              <1> 
  3662                              <1> 	;mov	al, opfls.size  ; mov al, 16
  3663                              <1> 	;
  3664                              <1> 	;mul	bl
  3665                              <1> 	;;mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3666                              <1> 	;; 27/03/2020
  3667                              <1> 	;mov	ebx, fsp-(opfls.size-opfls.offset) ; fsp-8
  3668                              <1> 	
  3669                              <1> 	;add	ebx, eax
  3670                              <1> 		; asl r1
  3671                              <1> 		; asl r1 / multiply by 8 to get index into 
  3672                              <1> 		       ; / fsp table entry
  3673                              <1> 		; asl r1
  3674                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3675                              <1> 			      ; / in the fsp entry
  3676                              <1> 	; 18/08/2020
  3677 00004BFA FECB                <1> 	dec	bl ; zero based fsp table entry number
  3678                              <1> 
  3679                              <1> ; temporary - 26/12/2021
  3680 00004BFC 881D[23420000]      <1> mov	[bytype], bl
  3681                              <1> 
  3682 00004C02 C0E304              <1> 	shl	bl, 4 ; * 16 ; opfls.size
  3683 00004C05 81C3[D86D0000]      <1> 	add	ebx, fsp+8 ; opfls.offset	
  3684                              <1> 	; ebx = address of the file offset pointer 
  3685                              <1> 	;	(not file offset! not fsp entry address !)
  3686                              <1> 
  3687 00004C0B 891D[48710000]      <1> 	mov	[u.fofp], ebx
  3688                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3689                              <1> 			     ; / in fsp entry in u.fofp
  3690                              <1> 	; 18/08/2020
  3691 00004C11 8A43FD              <1> 	mov	al, [ebx-3]  ; open mode & status flags
  3692                              <1> 
  3693 00004C14 50                  <1> 	push	eax
  3694                              <1> 
  3695                              <1> 	;mov	ax, [ebx]
  3696                              <1> 	;;mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3697                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3698                              <1> 			     ;;dev number is in 1 byte
  3699                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3700                              <1> 	
  3701                              <1> ; temporary - 26/12/2021
  3702 00004C15 53                  <1> push	ebx
  3703 00004C16 0205[96400000]      <1> add	al, [srwtype]
  3704 00004C1C 8B1D[1F420000]      <1> mov	ebx, [openaddr]
  3705 00004C22 8005[1F420000]02    <1> add	byte [openaddr], 2
  3706 00004C29 B44E                <1> mov	ah, 4Eh
  3707 00004C2B 668903              <1> mov	word [ebx], ax
  3708 00004C2E 8B1D[1F420000]      <1> mov	ebx, [openaddr]
  3709 00004C34 8005[1F420000]02    <1> add	byte [openaddr], 2
  3710 00004C3B A0[23420000]        <1> mov	al, [bytype]
  3711 00004C40 0430                <1> add	al, '0'
  3712 00004C42 668903              <1> mov	word [ebx], ax
  3713 00004C45 5B                  <1> pop	ebx
  3714                              <1> 
  3715                              <1> 	; 18/08/2020
  3716 00004C46 8A43FC              <1> 	mov	al, [ebx-4]  ; logical drive number
  3717                              <1> 
  3718 00004C49 A2[15710000]        <1> 	mov	[cdev], al
  3719                              <1> 
  3720                              <1> 	;dec	ebx
  3721                              <1> 	;dec	ebx
  3722                              <1> 	; 18/08/2020
  3723 00004C4E 668B43F8            <1> 	mov	ax, [ebx-8]
  3724                              <1> 		; mov -(r1),r1 / and the i-number r1
  3725                              <1> 
  3726 00004C52 5B                  <1> 	pop	ebx ; ebx = bl = open mode and status flag
  3727                              <1> 		; (bit 0 is open mode flag, 0 = read, 1 = write)
  3728                              <1> 	; eax = inode number (in ax)	
  3729                              <1> 
  3730                              <1> getf2:	; 18/08/2020
  3731                              <1> ;getf4:	; 1:
  3732 00004C53 C3                  <1> 	retn
  3733                              <1> 		; rts r0
  3734                              <1> 
  3735                              <1> 	; 19/12/2021
  3736                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3737                              <1> namei:
  3738                              <1> 	; 18/10/2021
  3739                              <1> 	; 12/06/2021
  3740                              <1> 	; 01/05/2021
  3741                              <1> 	; 26/03/2021
  3742                              <1> 	; 25/03/2021 (Retro UNIX 386 v2 - Beginning)
  3743                              <1> 	; 04/12/2015 (14 byte file names)
  3744                              <1> 	; 18/10/2015 (nbase, ncount)
  3745                              <1> 	; 12/10/2015
  3746                              <1> 	; 21/08/2015
  3747                              <1> 	; 18/07/2015
  3748                              <1> 	; 02/07/2015
  3749                              <1> 	; 17/06/2015
  3750                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3751                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3752                              <1> 	;
  3753                              <1> 	; 'namei' takes a file path name and returns i-number of
  3754                              <1> 	; the file in the current directory or the root directory
  3755                              <1> 	; (if the first character of the pathname is '/').	
  3756                              <1> 	;
  3757                              <1> 	; INPUTS ->
  3758                              <1> 	;    u.namep - points to a file path name
  3759                              <1> 	;    u.cdir - i-number of users directory
  3760                              <1> 	;    u.cdev - device number on which user directory resides	
  3761                              <1> 	; OUTPUTS ->
  3762                              <1> 	;    r1 - i-number of file
  3763                              <1> 	;    cdev
  3764                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3765                              <1> 	;               occurs in the search for file path name.
  3766                              <1> 	;	        If no match u.dirb points to the end of 
  3767                              <1> 	;               the directory and r1 = i-number of the current
  3768                              <1> 	;	        directory.	
  3769                              <1> 	; ((AX = R1))
  3770                              <1> 	;
  3771                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3772                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3773                              <1> 	;
  3774                              <1> 
  3775                              <1> 	;mov	ax, [u.cdir]
  3776                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3777                              <1> 			      ; / in r1
  3778                              <1> 	; 01/05/2021
  3779 00004C54 A1[38710000]        <1> 	mov	eax, [u.cdir]	
  3780 00004C59 8A15[3C710000]      <1> 	mov	dl, [u.cdrv]
  3781 00004C5F 8815[15710000]      <1> 	mov	[cdev], dl
  3782                              <1> 	;mov	dx, [u.cdrv]
  3783                              <1> 	;mov	[cdev], dx	; NOTE: Retro UNIX 8086 v1 
  3784                              <1> 				; device/drive number is in 1 byte, 
  3785                              <1> 				; not in 1 word!
  3786                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3787                              <1> 				; / into cdev
  3788                              <1> 	; 12/10/2015
  3789                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3790                              <1>       	; convert virtual (pathname) addr to physical address
  3791 00004C65 E80D010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3792                              <1> 		; esi = physical address of [u.namep]
  3793                              <1> 		; ecx = byte count in the page
  3794 00004C6A 803E2F              <1> 	cmp	byte [esi], '/'
  3795                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3796 00004C6D 751C                <1> 	jne	short namei_1
  3797                              <1> 		; bne 1f
  3798 00004C6F FF05[50710000]      <1> 	inc	dword [u.namep]
  3799                              <1> 		; inc u.namep / go to next char
  3800                              <1> 	;dec	cx ; remain byte count in the page
  3801 00004C75 49                  <1> 	dec	ecx ; 18/10/2021
  3802 00004C76 7506                <1> 	jnz	short namei_0
  3803                              <1> 	; 12/10/2015
  3804 00004C78 E8FA000000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3805                              <1> 		; esi = physical address (page start + offset)
  3806                              <1> 		; ecx = byte count in the page
  3807 00004C7D 4E                  <1> 	dec	esi
  3808                              <1> namei_0:
  3809 00004C7E 46                  <1> 	inc 	esi  ; go to next char
  3810                              <1> 	;mov	ax, [rootdir] ; 09/07/2013
  3811                              <1> 	; 18/10/2021
  3812 00004C7F A1[1C710000]        <1> 	mov	eax, [rootdir]
  3813                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3814 00004C84 C605[15710000]00    <1> 	mov	byte [cdev], 0
  3815                              <1> 		; clr cdev / clear device number
  3816                              <1> namei_1: ; 1:
  3817 00004C8B F606FF              <1> 	test	byte [esi], 0FFh
  3818                              <1> 	;jz	short getf4
  3819                              <1> 	; 26/03/2021
  3820                              <1> 	;jz	short getf2 ; retn
  3821                              <1> 	;;jz	nig
  3822                              <1> 		; tstb *u.namep / is the character in file name a nul
  3823                              <1> 		; beq nig / yes, end of file name reached; 
  3824                              <1> 			; / branch to "nig"
  3825                              <1> 	; 19/12/2021
  3826                              <1> namei_9:
  3827                              <1> 	; 12/06/2021
  3828 00004C8E 7501                <1> 	jnz	short namei_2
  3829 00004C90 C3                  <1> 	retn
  3830                              <1> namei_2: ; 1:
  3831                              <1> 	; 18/10/2015
  3832 00004C91 8935[F8710000]      <1> 	mov 	[nbase], esi
  3833                              <1> 	;mov 	[ncount], cx
  3834                              <1> 	; 18/10/2021
  3835 00004C97 890D[FC710000]      <1> 	mov	[ncount], ecx
  3836                              <1> 	;
  3837                              <1> 	;;mov	dx, 2
  3838                              <1> 	;mov	dl, 2 ; user flag (read, non-owner)
  3839                              <1> 	; 25/03/2021
  3840                              <1> 	;mov	dx, 100h ; IREAD - read, owner 
  3841                              <1> 	; 18/10/2021
  3842 00004C9D 29D2                <1> 	sub	edx, edx
  3843 00004C9F FEC6                <1> 	inc	dh ; dx = 100h ; IREAD - read, owner 
  3844 00004CA1 E8280A0000          <1> 	call	access
  3845                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3846                              <1> 	; 'access' will not return here if user has not "r" permission !
  3847                              <1> 
  3848                              <1> ; temporary - 11/12/2021
  3849                              <1> ;mov	dword [0B8000h], 4E334E33h
  3850                              <1> ;mov	ecx, 0FFFFh
  3851                              <1> ;abovec:
  3852                              <1> ;dec	edx
  3853                              <1> ;inc	edx
  3854                              <1> ;loop	abovec
  3855                              <1> 
  3856                              <1> 	;test 	word [i.flgs], 4000h
  3857                              <1> 	;	; bit $40000,i.flgs / directory i-node?
  3858                              <1>         ;jz	short namei_err
  3859                              <1> 		; beq error3 / no, got an error
  3860                              <1> 	; 26/03/2021 
  3861                              <1> ;	mov	al, [i.flgs+1]
  3862                              <1> ;	;test	al, 80h ; IFREG ; 80h
  3863                              <1> ;	;jz	short namei_err ; not a regular file ! (device!?)
  3864                              <1> ;	;and	al, 40h ; IFDIR ; 40h
  3865                              <1> ;	;jz	short namei_err ; not a sub directory !
  3866                              <1> ;	shl	al, 1 ; 80h (IFREG flag) -> cf = 1
  3867                              <1> ;	jnc	short namei_err ; not a regular file ! (device!?)
  3868                              <1> ;	shl	al, 1 ; 80h (IFDIR flag) -> cf = 1
  3869                              <1> ;	jnc	short namei_err ; not a sub directory !
  3870                              <1> 
  3871                              <1> 	; 27/03/2021
  3872 00004CA6 E8FD000000          <1> 	call	chk_dir ; check for directory, jump to 'error' if not
  3873                              <1> 	; CPU will be here if the inode is a (valid) directory inode
  3874                              <1> 
  3875                              <1> ; temporary - 11/12/2021
  3876                              <1> ;mov	dword [0B8004h], 4E384E38h
  3877                              <1> ;mov	ecx, 0FFFFFh
  3878                              <1> ;aboved:
  3879                              <1> ;dec	edx
  3880                              <1> ;inc	edx
  3881                              <1> ;loop	aboved
  3882                              <1> 
  3883                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3884                              <1> 	;xor	eax, eax
  3885                              <1> 	;mov	[u.off], eax ; 0
  3886                              <1> 	; 01/05/2021 - Retro UNIX 386 v2 inode structure
  3887 00004CAB A1[D86D0000]        <1> 	mov	eax, [i.size]
  3888                              <1> 	;mov	ax, [i.size]
  3889 00004CB0 A3[4C710000]        <1> 	mov	[u.dirp], eax
  3890                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3891                              <1> 		; clr u.off / u.off is file offset used by user
  3892                              <1> 	; 18/10/2021
  3893 00004CB5 31C0                <1> 	xor	eax, eax
  3894                              <1> 	;mov	[u.off], eax ; 0
  3895 00004CB7 BB[54710000]        <1> 	mov	ebx, u.off
  3896 00004CBC 8903                <1> 	mov	[ebx], eax ; mov dword [u.off], 0
  3897                              <1> 	;
  3898 00004CBE 891D[48710000]      <1> 	mov	[u.fofp], ebx ; u.off ; 18/10/2021
  3899                              <1> 	;mov	dword [u.fofp], u.off
  3900                              <1> 			; mov $u.off,u.fofp / u.fofp is a pointer to 
  3901                              <1> 				  ; / the offset portion of fsp entry
  3902                              <1> namei_3: ; 2:
  3903 00004CC4 C705[5C710000]-     <1> 	mov	dword [u.base], u.dirbuf
  3903 00004CCA [70710000]          <1>
  3904                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3905                              <1> 				    ; / copied from a directory
  3906 00004CCE C705[60710000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3906 00004CD6 0000                <1>
  3907                              <1>  		; mov $10.,u.count / u.count is byte count 
  3908                              <1> 				 ; / for reads and writes
  3909                              <1> 	;mov 	ax, [ii]
  3910                              <1> 	; 18/10/2021
  3911 00004CD8 A1[10710000]        <1> 	mov	eax, [ii] ; (32 bit inode number)
  3912                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3913 00004CDD FE05[AA710000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3914 00004CE3 E8680B0000          <1>     	call	readi
  3915                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3916                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3917                              <1> 
  3918 00004CE8 8B0D[64710000]      <1> 	mov 	ecx, [u.nread]
  3919 00004CEE 09C9                <1> 	or 	ecx, ecx
  3920                              <1> 		; tst u.nread
  3921 00004CF0 741A                <1> 	jz	short nib
  3922                              <1> 		; ble nib / gives error return
  3923                              <1> 	;
  3924                              <1> 	;mov 	bx, [u.dirbuf]
  3925                              <1> 	;and 	bx, bx       
  3926                              <1> 	; 18/10/2021
  3927 00004CF2 66F705[70710000]FF- <1> 	test	word [u.dirbuf], 0FFFFh
  3927 00004CFA FF                  <1>
  3928                              <1> 		; tst u.dirbuf /
  3929 00004CFB 7513                <1> 	jnz	short namei_4
  3930                              <1> 		; bne 3f / branch when active directory entry 
  3931                              <1> 		       ; / (i-node word in entry non zero)
  3932 00004CFD A1[54710000]        <1> 	mov	eax, [u.off]
  3933 00004D02 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3934 00004D05 A3[4C710000]        <1> 	mov	[u.dirp], eax
  3935                              <1> 		; mov u.off,u.dirp
  3936                              <1> 		; sub $10.,u.dirp
  3937 00004D0A EBB8                <1> 	jmp	short namei_3
  3938                              <1> 		; br 2b
  3939                              <1> 
  3940                              <1> 	; 18/07/2013
  3941                              <1> nib: 
  3942 00004D0C 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3943 00004D0E F9                  <1> 	stc
  3944                              <1> nig:
  3945 00004D0F C3                  <1> 	retn
  3946                              <1> 
  3947                              <1> 	; 27/03/2021
  3948                              <1> ;namei_err:
  3949                              <1> 	; 16/06/2015
  3950                              <1> ;	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3951                              <1> ;	jmp	error
  3952                              <1> 
  3953                              <1> namei_4: ; 3:
  3954                              <1> 	; 18/10/2015
  3955                              <1> 	; 12/10/2015
  3956                              <1> 	; 21/08/2015
  3957                              <1> 	; 18/07/2015
  3958 00004D10 8B2D[50710000]      <1> 	mov	ebp, [u.namep]
  3959                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3960 00004D16 BF[72710000]        <1> 	mov 	edi, u.dirbuf + 2
  3961                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3962                              <1> 	; 18/10/2015
  3963 00004D1B 8B35[F8710000]      <1> 	mov	esi, [nbase]
  3964                              <1> 	;mov	cx, [ncount]
  3965                              <1> 	;and	cx, cx
  3966                              <1> 	; 18/10/2021
  3967 00004D21 8B0D[FC710000]      <1> 	mov	ecx, [ncount]
  3968 00004D27 21C9                <1> 	and	ecx, ecx
  3969 00004D29 7505                <1> 	jnz	short namei_5	
  3970                              <1> 	;
  3971 00004D2B E84D000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3972                              <1> 		; esi = physical address (page start + offset)
  3973                              <1> 		; ecx = byte count in the page
  3974                              <1> namei_5: ; 3:
  3975 00004D30 45                  <1> 	inc	ebp ; 18/07/2015
  3976 00004D31 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3977                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3978 00004D32 08C0                <1> 	or 	al, al
  3979 00004D34 741C                <1> 	jz 	short namei_7
  3980                              <1> 		; beq 3f / if char is nul, then the last char in string
  3981                              <1> 			; / has been moved
  3982 00004D36 3C2F                <1> 	cmp	al, '/'
  3983                              <1> 		; cmp r4,$'/ / is char a </>
  3984 00004D38 7418                <1> 	je 	short namei_7
  3985                              <1> 		; beq 3f	
  3986                              <1> 	; 12/10/2015
  3987                              <1> 	;dec	cx ; remain byte count in the page
  3988 00004D3A 49                  <1> 	dec	ecx ; 18/10/2021
  3989 00004D3B 7505                <1> 	jnz	short namei_6
  3990 00004D3D E83B000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3991                              <1> 		; esi = physical address (page start + offset)
  3992                              <1> 		; ecx = byte count in the page
  3993                              <1> namei_6:
  3994 00004D42 81FF[80710000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3995                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3996                              <1> 				     ; / all 8 bytes of file name
  3997 00004D48 74E6                <1> 	je	short namei_5
  3998                              <1> 		; beq 3b
  3999 00004D4A AE                  <1> 	scasb	
  4000                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  4001                              <1> 			      ; / char read from directory
  4002 00004D4B 74E3                <1> 	je 	short namei_5
  4003                              <1> 		; beq 3b / branch if chars match
  4004                              <1> 
  4005 00004D4D E972FFFFFF          <1>         jmp	namei_3 ; 2b
  4006                              <1> 		; br 2b / file names do not match go to next directory entry
  4007                              <1> namei_7: ; 3:
  4008 00004D52 81FF[80710000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  4009                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  4010 00004D58 7409                <1> 	je	short namei_8
  4011                              <1> 		; beq 3f
  4012                              <1> 	;mov 	ah, [edi]
  4013                              <1> 	;;inc 	edi 
  4014                              <1> 	;and 	ah, ah
  4015                              <1> 	;	; tstb (r3)+ /
  4016                              <1>         ; 18/10/2021
  4017 00004D5A F607FF              <1> 	test	byte [edi], 0FFh
  4018 00004D5D 0F8561FFFFFF        <1> 	jnz	namei_3
  4019                              <1> 		; bne 2b
  4020                              <1> namei_8: ; 3
  4021 00004D63 892D[50710000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  4022                              <1> 		; mov r2,u.namep / u.namep points to char 
  4023                              <1> 			       ; / following a / or nul
  4024                              <1> 	;mov	bx, [u.dirbuf]
  4025                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  4026                              <1> 				; / entry to r1
  4027 00004D69 20C0                <1> 	and 	al, al
  4028                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  4029                              <1> 		      ;  / if r4 = </> then go to next directory
  4030                              <1> 	;mov	ax, bx
  4031                              <1> 	;mov 	ax, [u.dirbuf] ; 17/06/2015
  4032                              <1>         ; 18/10/2021 (16 bit inode number in 32 bit register)
  4033 00004D6B 0FB705[70710000]    <1> 	movzx	eax, word [u.dirbuf] 
  4034                              <1> 	; 19/12/2021
  4035 00004D72 E917FFFFFF          <1> 	jmp	namei_9 ; eax = inode number
  4036                              <1> ;	jnz	namei_2 
  4037                              <1> ;		; bne 1b
  4038                              <1> ;	; AX = i-number of the file
  4039                              <1> ;;;nig:
  4040                              <1> ;	retn
  4041                              <1> 		; tst (r0)+ / gives non-error return
  4042                              <1> ;;nib:
  4043                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  4044                              <1> 		       ; ax = 0 -> file not found 
  4045                              <1> ;;	stc	; 27/05/2013
  4046                              <1> ;;	retn
  4047                              <1> 		; rts r0
  4048                              <1> 
  4049                              <1> trans_addr_nmbp:
  4050                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4051                              <1> 	; 18/10/2015
  4052                              <1> 	; 12/10/2015
  4053 00004D77 8B2D[50710000]      <1> 	mov 	ebp, [u.namep]
  4054                              <1> trans_addr_nm: 
  4055                              <1> 	; 18/10/2021 - Retro UNIX 386 v2
  4056                              <1> 	; Convert virtual (pathname) address to physical address
  4057                              <1> 	; (Retro UNIX 386 v1 feature only !)
  4058                              <1> 	; 18/10/2015
  4059                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  4060                              <1> 	; 02/07/2015
  4061                              <1> 	; 17/06/2015
  4062                              <1> 	; 16/06/2015
  4063                              <1> 	;
  4064                              <1> 	; INPUTS: 
  4065                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  4066                              <1> 	;	[u.pgdir] = user's page directory
  4067                              <1> 	; OUTPUT:
  4068                              <1> 	;       esi = physical address of the pathname
  4069                              <1> 	;	ecx = remain byte count in the page
  4070                              <1> 	;
  4071                              <1> 	; (Modified registers: EBX, ECX, EDX, ESI) ; 18/10/2021
  4072                              <1> 	;
  4073                              <1> 
  4074                              <1> 	; 18/10/2021
  4075 00004D7D 29C9                <1> 	sub	ecx, ecx
  4076                              <1> 	;
  4077                              <1>         ;cmp	dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  4078 00004D7F 390D[9C710000]      <1> 	cmp	[u.ppgdir], ecx ; 0 ; 18/10/2021
  4079 00004D85 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  4080                              <1> 				     ; it is already physical address
  4081 00004D87 50                  <1>    	push	eax	
  4082 00004D88 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  4083 00004D8A E8CDE5FFFF          <1>        	call	get_physical_addr ; get physical address
  4084 00004D8F 7204                <1> 	jc	short tr_addr_nm_err
  4085                              <1> 	; 18/10/2015
  4086                              <1> 	; eax = physical address 
  4087                              <1> 	; ecx = remain byte count in page (1-4096) ; 18/10/2021
  4088                              <1> 		; 12/10/2015 (cx = [u.pncount])
  4089 00004D91 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  4090 00004D93 58                  <1> 	pop	eax 
  4091 00004D94 C3                  <1> 	retn
  4092                              <1> 
  4093                              <1> tr_addr_nm_err:
  4094 00004D95 A3[AC710000]        <1> 	mov	[u.error], eax
  4095                              <1> 	;pop 	eax
  4096 00004D9A E928EFFFFF          <1> 	jmp	error
  4097                              <1> 
  4098                              <1> trans_addr_nmk:
  4099                              <1> 	; 12/10/2015
  4100                              <1> 	; 02/07/2015
  4101 00004D9F 8B35[50710000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  4102                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  4103                              <1> 	; 18/10/2021
  4104 00004DA5 B510                <1> 	mov	ch, PAGE_SIZE/256
  4105 00004DA7 C3                  <1> 	retn
  4106                              <1> 
  4107                              <1> 
  4108                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4109                              <1> chk_dir:
  4110                              <1> 	; 12/06/2021
  4111                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  4112                              <1> 	; Check for directory inode
  4113                              <1> 
  4114 00004DA8 8A0D[D16D0000]      <1> 	mov	cl, [i.flgs+1]
  4115                              <1> 	;test	cl, 80h ; IFREG ; 80h
  4116                              <1> 	;jz	short chk_dir_err ; not a regular file ! (device!?)
  4117                              <1> 	;and	cl, 40h ; IFDIR ; 40h
  4118                              <1> 	;jz	short chk_dir_err ; not a sub directory !
  4119 00004DAE D0E1                <1> 	shl	cl, 1 ; 80h (IFREG flag) -> cf = 1
  4120 00004DB0 7305                <1> 	jnc	short chk_dir_err ; not a regular file ! (device!?)
  4121 00004DB2 D0E1                <1> 	shl	cl, 1 ; 80h (IFDIR flag) -> cf = 1
  4122 00004DB4 7301                <1> 	jnc	short chk_dir_err ; not a sub directory !
  4123                              <1> 	; 12/06/2021
  4124 00004DB6 C3                  <1> 	retn
  4125                              <1> chk_dir_err:
  4126 00004DB7 C705[AC710000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4126 00004DBF 0000                <1>
  4127 00004DC1 E901EFFFFF          <1> 	jmp	error
  4128                              <1> 
  4129                              <1> syschdir:
  4130                              <1> 	; / makes the directory specified in the argument
  4131                              <1> 	; / the current directory
  4132                              <1> 	;
  4133                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4134                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  4135                              <1> 	;
  4136                              <1> 	; 'syschdir' makes the directory specified in its argument
  4137                              <1> 	; the current working directory.
  4138                              <1> 	;
  4139                              <1> 	; Calling sequence:
  4140                              <1> 	;	syschdir; name
  4141                              <1> 	; Arguments:
  4142                              <1> 	;	name - address of the path name of a directory
  4143                              <1> 	;	       terminated by nul byte.	
  4144                              <1> 	; Inputs: -
  4145                              <1> 	; Outputs: -
  4146                              <1> 	; ...............................................................
  4147                              <1> 	;				
  4148                              <1> 	; Retro UNIX 8086 v1 modification:
  4149                              <1> 	;	 The user/application program puts address of 
  4150                              <1> 	;	 the path name in BX register as 'syschdir' 
  4151                              <1> 	; 	 system call argument.
  4152                              <1> 
  4153 00004DC6 891D[50710000]      <1> 	mov	[u.namep], ebx
  4154                              <1> 		;jsr r0,arg; u.namep / u.namep points to path name
  4155 00004DCC E883FEFFFF          <1> 	call	namei
  4156                              <1> 		; jsr r0,namei / find its i-number
  4157                              <1> 	;jc	error
  4158                              <1> 		; br error3
  4159 00004DD1 730F                <1> 	jnc	short syschdir0
  4160                              <1> 	; 'directory not found !' error
  4161 00004DD3 C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  4161 00004DDB 0000                <1>
  4162 00004DDD E9E5EEFFFF          <1> 	jmp	error
  4163                              <1> syschdir0:
  4164 00004DE2 E8E7080000          <1> 	call	access
  4165                              <1> 		; jsr r0,access; 2 / get i-node into core
  4166 00004DE7 66F705[D06D0000]00- <1> 	test	word [i.flgs], 4000h
  4166 00004DEF 40                  <1>
  4167                              <1> 		; bit $40000,i.flgs / is it a directory?
  4168                              <1> 	;jz	error 
  4169                              <1> 		; beq error3 / no error
  4170 00004DF0 750F                <1> 	jnz	short syschdir1
  4171 00004DF2 C705[AC710000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  4171 00004DFA 0000                <1>
  4172 00004DFC E9C6EEFFFF          <1> 	jmp	error
  4173                              <1> syschdir1:
  4174 00004E01 66A3[38710000]      <1> 	mov	[u.cdir], ax
  4175                              <1> 		; mov r1,u.cdir / move i-number to users 
  4176                              <1> 			      ; / current directory
  4177 00004E07 66A1[15710000]      <1> 	mov	ax, [cdev]
  4178 00004E0D 66A3[3C710000]      <1> 	mov	[u.cdrv], ax
  4179                              <1> 		; mov cdev,u.cdev / move its device to users 
  4180                              <1> 			        ; / current device
  4181 00004E13 E9CFEEFFFF          <1> 	jmp	sysret
  4182                              <1> 		; br sysret3
  4183                              <1> 	
  4184                              <1> syschmod: ; < change mode of file >
  4185                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4186                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4187                              <1> 	;
  4188                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  4189                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  4190                              <1> 	; changed to 'mode'.
  4191                              <1> 	;
  4192                              <1> 	; Calling sequence:
  4193                              <1> 	;	syschmod; name; mode
  4194                              <1> 	; Arguments:
  4195                              <1> 	;	name - address of the file name
  4196                              <1> 	;	       terminated by null byte.
  4197                              <1> 	;	mode - (new) mode/flags < attributes >
  4198                              <1> 	;	
  4199                              <1> 	; Inputs: -
  4200                              <1> 	; Outputs: -
  4201                              <1> 	; ...............................................................
  4202                              <1> 	;				
  4203                              <1> 	; Retro UNIX 8086 v1 modification: 
  4204                              <1> 	;       'syschmod' system call has two arguments; so,
  4205                              <1> 	;	* 1st argument, name is pointed to by BX register
  4206                              <1> 	;	* 2nd argument, mode is in CX register
  4207                              <1> 	;
  4208                              <1> 	; Mode bits (Flags):
  4209                              <1> 	;	bit 0 - write permission for non-owner (1)
  4210                              <1> 	;	bit 1 - read permission for non-owner (2)
  4211                              <1> 	;	bit 2 - write permission for owner (4)
  4212                              <1> 	;	bit 3 - read permission for owner (8)
  4213                              <1> 	;	bit 4 - executable flag (16) 	
  4214                              <1> 	;	bit 5 - set user ID on execution flag (32) 
  4215                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  4216                              <1> 	;	bit 12 - large file flag (4096)
  4217                              <1> 	;	bit 13 - file has modified flag (always on) (8192)
  4218                              <1> 	;	bit 14 - directory flag (16384)
  4219                              <1> 	;	bit 15 - 'i-node is allocated' flag (32768)
  4220                              <1> 
  4221                              <1> 	; / name; mode
  4222 00004E18 E814000000          <1> 	call	isown
  4223                              <1> 		;jsr r0,isown / get the i-node and check user status
  4224 00004E1D 66F705[D06D0000]00- <1> 	test	word [i.flgs], 4000h
  4224 00004E25 40                  <1>
  4225                              <1> 		; bit	$40000,i.flgs / directory?
  4226 00004E26 7402                <1> 	jz	short syschmod1
  4227                              <1> 		; beq 2f / no
  4228                              <1> 	; AL = (new) mode
  4229 00004E28 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  4230                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  4231                              <1> 			   ; / executable modes
  4232                              <1> syschmod1: ; 2:
  4233 00004E2A A2[D06D0000]        <1> 	mov	[i.flgs], al	
  4234                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  4235 00004E2F EB42                <1> 	jmp	short isown1
  4236                              <1> 		; br 1f
  4237                              <1> 
  4238                              <1> isown:
  4239                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4240                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  4241                              <1> 	;
  4242                              <1> 	; 'isown' is given a file name (the 1st argument).
  4243                              <1> 	;  It find the i-number of that file via 'namei' 
  4244                              <1> 	;  then gets the i-node into core via 'iget'.
  4245                              <1> 	;  It then tests to see if the user is super user. 
  4246                              <1> 	;  If not, it cheks to see if the user is owner of 
  4247                              <1> 	;  the file. If he is not an error occurs.
  4248                              <1> 	;  If user is the owner 'setimod' is called to indicate
  4249                              <1> 	;  the inode has been modificed and the 2nd argument of
  4250                              <1> 	;  the call is put in r2.
  4251                              <1> 	;
  4252                              <1> 	; INPUTS ->
  4253                              <1> 	;    arguments of syschmod and syschown calls
  4254                              <1> 	; OUTPUTS ->
  4255                              <1> 	;    u.uid - id of user
  4256                              <1> 	;    imod - set to a 1
  4257                              <1> 	;    r2 - contains second argument of the system call				 	
  4258                              <1> 	;
  4259                              <1> 	;   ((AX=R2) output as 2nd argument)
  4260                              <1> 	;
  4261                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4262                              <1> 	;
  4263                              <1> 		; jsr r0,arg2 / u.namep points to file name
  4264                              <1> 	;; ! 2nd argument on top of stack !
  4265                              <1> 	;; 22/06/2015 - 32 bit modifications
  4266                              <1> 	;; 07/07/2013
  4267 00004E31 891D[50710000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4268 00004E37 51                  <1> 	push 	ecx ;; 2nd argument
  4269                              <1> 	;;
  4270 00004E38 E817FEFFFF          <1> 	call	namei
  4271                              <1> 		; jsr r0,namei / get its i-number
  4272                              <1>        ; Retro UNIX 8086 v1 modification !
  4273                              <1>        ; ax = 0 -> file not found 
  4274                              <1> 	;and	ax, ax
  4275                              <1> 	;jz	error
  4276                              <1> 	;jc	error ; 27/05/2013
  4277                              <1> 		; br error3
  4278 00004E3D 730F                <1> 	jnc	short isown0
  4279                              <1> 	; 'file not found !' error
  4280 00004E3F C705[AC710000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4280 00004E47 0000                <1>
  4281 00004E49 E979EEFFFF          <1> 	jmp	error
  4282                              <1> isown0:
  4283 00004E4E E894070000          <1> 	call	iget
  4284                              <1> 		; jsr r0,iget / get i-node into core
  4285 00004E53 A0[8A710000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4286 00004E58 08C0                <1> 	or	al, al
  4287                              <1> 		; tstb u.uid / super user?
  4288 00004E5A 7417                <1> 	jz	short isown1
  4289                              <1> 		; beq 1f / yes, branch
  4290 00004E5C 3A05[D46D0000]      <1> 	cmp	al, [i.uid]
  4291                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4292                              <1> 				 ; / the file
  4293                              <1> 	;jne	error
  4294                              <1> 		; beq 1f / yes
  4295                              <1> 		; jmp error3 / no, error
  4296 00004E62 740F                <1> 	je	short isown1
  4297                              <1> 
  4298 00004E64 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4298 00004E6C 0000                <1>
  4299                              <1> 			;  'permission denied !' error
  4300 00004E6E E954EEFFFF          <1> 	jmp	error
  4301                              <1> isown1: ; 1:
  4302 00004E73 E80B090000          <1> 	call	setimod
  4303                              <1> 		; jsr r0,setimod / indicates 
  4304                              <1> 		;	       ; / i-node has been modified
  4305 00004E78 58                  <1> 	pop	eax ; 2nd argument
  4306                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4307                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4308 00004E79 C3                  <1> 	retn
  4309                              <1> 		; rts r0
  4310                              <1> 
  4311                              <1> ;;arg:  ; < get system call arguments >
  4312                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4313                              <1> 	; of form:
  4314                              <1> 	;	sys 'routine' ; arg1
  4315                              <1> 	;		or
  4316                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4317                              <1> 	;		or
  4318                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4319                              <1> 	;	
  4320                              <1> 	; INPUTS ->
  4321                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4322                              <1> 	;	This pointers's value is actually the value of
  4323                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4324                              <1> 	;	made to process the sys instruction
  4325                              <1> 	;    r0 - contains the return address for the routine
  4326                              <1> 	;	that called arg. The data in the word pointer 
  4327                              <1> 	;	to by the return address is used as address
  4328                              <1> 	;	in which the extracted argument is stored   		
  4329                              <1> 	;    	
  4330                              <1> 	; OUTPUTS ->
  4331                              <1> 	;    'address' - contains the extracted argument 
  4332                              <1> 	;    u.sp+18 - is incremented by 2 
  4333                              <1> 	;    r1 - contains the extracted argument
  4334                              <1> 	;    r0 - points to the next instruction to be
  4335                              <1> 	;	 executed in the calling routine.
  4336                              <1> 	;
  4337                              <1>   
  4338                              <1> 	; mov u.sp,r1
  4339                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4340                              <1> 			; / into argument of arg2
  4341                              <1> 	; add $2,18.(r1) / point pc on stack 
  4342                              <1> 			      ; / to next system argument
  4343                              <1> 	; rts r0
  4344                              <1> 
  4345                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4346                              <1> 	; 'arg2' takes first argument in system call
  4347                              <1> 	;  (pointer to name of the file) and puts it in location
  4348                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4349                              <1> 	;  and on top of the stack
  4350                              <1> 	;	
  4351                              <1> 	; INPUTS ->
  4352                              <1> 	;    u.sp, r0
  4353                              <1> 	;    	
  4354                              <1> 	; OUTPUTS ->
  4355                              <1> 	;    u.namep
  4356                              <1> 	;    u.off 
  4357                              <1> 	;    u.off pushed on stack
  4358                              <1> 	;    r1
  4359                              <1> 	;
  4360                              <1> 
  4361                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4362                              <1> 				; / first arg in sys call
  4363                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4364                              <1> 				; / second arg in sys call
  4365                              <1> 	; mov r0,r1 / r0 points to calling routine
  4366                              <1> 	; mov (sp),r0 / put operation code back in r0
  4367                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4368                              <1> 			; / on stack
  4369                              <1> 	; jmp (r1) / return to calling routine
  4370                              <1> 
  4371                              <1> syschown: ; < change owner of file >
  4372                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4373                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4374                              <1> 	;
  4375                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4376                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4377                              <1> 	; changed to 'owner'
  4378                              <1> 	;
  4379                              <1> 	; Calling sequence:
  4380                              <1> 	;	syschown; name; owner
  4381                              <1> 	; Arguments:
  4382                              <1> 	;	name - address of the file name
  4383                              <1> 	;	       terminated by null byte.
  4384                              <1> 	;	owner - (new) owner (number/ID)
  4385                              <1> 	;	
  4386                              <1> 	; Inputs: -
  4387                              <1> 	; Outputs: -
  4388                              <1> 	; ...............................................................
  4389                              <1> 	;				
  4390                              <1> 	; Retro UNIX 8086 v1 modification: 
  4391                              <1> 	;       'syschown' system call has two arguments; so,
  4392                              <1> 	;	* 1st argument, name is pointed to by BX register
  4393                              <1> 	;	* 2nd argument, owner number is in CX register
  4394                              <1> 	;
  4395                              <1> 	; / name; owner
  4396 00004E7A E8B2FFFFFF          <1> 	call	isown
  4397                              <1> 		; jsr r0,isown / get the i-node and check user status
  4398 00004E7F 803D[8A710000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4399                              <1> 		; tstb u.uid / super user
  4400 00004E86 7418                <1> 	jz	short syschown1
  4401                              <1> 		; beq 2f / yes, 2f
  4402 00004E88 F605[D06D0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4403                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4404                              <1> 	;jnz	error
  4405                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4406 00004E8F 740F                <1> 	jz	short syschown1
  4407                              <1> 	; 'permission denied !'
  4408 00004E91 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4408 00004E99 0000                <1>
  4409 00004E9B E927EEFFFF          <1> 	jmp	error
  4410                              <1> syschown1: ; 2:
  4411                              <1> 	; AL = owner (number/ID)
  4412 00004EA0 A2[D46D0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4413                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4414                              <1> 			       ; / in the i-node
  4415 00004EA5 E93DEEFFFF          <1> 	jmp	sysret
  4416                              <1> 	; 1: 
  4417                              <1> 		; jmp sysret4
  4418                              <1> 	; 3:
  4419                              <1> 		; jmp	error
  4420                              <1> 
  4421                              <1> systime: ; / get time of year
  4422                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4423                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4424                              <1> 	;
  4425                              <1> 	; 20/06/2013
  4426                              <1> 	; 'systime' gets the time of the year.
  4427                              <1> 	; The present time is put on the stack.
  4428                              <1> 	;
  4429                              <1> 	; Calling sequence:
  4430                              <1> 	;	systime
  4431                              <1> 	; Arguments: -
  4432                              <1> 	;	
  4433                              <1> 	; Inputs: -
  4434                              <1> 	; Outputs: sp+2, sp+4 - present time
  4435                              <1> 	; ...............................................................
  4436                              <1> 	;	
  4437                              <1> 	; Retro UNIX 8086 v1 modification: 
  4438                              <1> 	;       'systime' system call will return to the user
  4439                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4440                              <1> 	;
  4441                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4442                              <1> 	;	system call for PC compatibility !!		 	
  4443                              <1> 
  4444 00004EAA E841E9FFFF          <1> 	call 	epoch
  4445 00004EAF A3[34710000]        <1> 	mov 	[u.r0], eax
  4446                              <1> 		; mov s.time,4(sp)
  4447                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4448                              <1> 				   ; / on the stack
  4449                              <1> 		; br sysret4
  4450 00004EB4 E92EEEFFFF          <1> 	jmp	sysret 
  4451                              <1> 
  4452                              <1> sysstime: ; / set time
  4453                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4454                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4455                              <1> 	;
  4456                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4457                              <1> 	;
  4458                              <1> 	; Calling sequence:
  4459                              <1> 	;	sysstime
  4460                              <1> 	; Arguments: -
  4461                              <1> 	;	
  4462                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4463                              <1> 	; Outputs: -
  4464                              <1> 	; ...............................................................
  4465                              <1> 	;	
  4466                              <1> 	; Retro UNIX 8086 v1 modification: 
  4467                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4468                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4469                              <1> 	; 
  4470                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4471                              <1> 	;	to get sysstime system call arguments from the user;
  4472                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4473                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4474                              <1> 	;
  4475                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4476                              <1> 	;	system call for PC compatibility !!	
  4477                              <1> 
  4478 00004EB9 803D[8A710000]00    <1> 	cmp	byte [u.uid], 0
  4479                              <1> 		; tstb u.uid / is user the super user
  4480                              <1> 	;ja	error
  4481                              <1> 		; bne error4 / no, error
  4482 00004EC0 760F                <1> 	jna	short systime1
  4483                              <1> 	; 'permission denied !'
  4484 00004EC2 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4484 00004ECA 0000                <1>
  4485 00004ECC E9F6EDFFFF          <1> 	jmp	error
  4486                              <1> systime1:
  4487                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4488                              <1> 	; EBX = unix (epoch) time (from user)
  4489 00004ED1 89D8                <1> 	mov	eax, ebx
  4490 00004ED3 E898EAFFFF          <1> 	call 	set_date_time
  4491                              <1> 		; mov 4(sp),s.time
  4492                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4493 00004ED8 E90AEEFFFF          <1> 	jmp	sysret
  4494                              <1> 		; br sysret4
  4495                              <1> 
  4496                              <1> sysbreak:
  4497                              <1> 	; 18/10/2015
  4498                              <1> 	; 07/10/2015
  4499                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4500                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4501                              <1> 	;
  4502                              <1> 	; 'sysbreak' sets the programs break points. 
  4503                              <1> 	; It checks the current break point (u.break) to see if it is
  4504                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4505                              <1> 	; even address (if it was odd) and the area between u.break
  4506                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4507                              <1> 	; in u.break and control is passed to 'sysret'.
  4508                              <1> 	;
  4509                              <1> 	; Calling sequence:
  4510                              <1> 	;	sysbreak; addr
  4511                              <1> 	; Arguments: -
  4512                              <1> 	;	
  4513                              <1> 	; Inputs: u.break - current breakpoint
  4514                              <1> 	; Outputs: u.break - new breakpoint 
  4515                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4516                              <1> 	; ...............................................................
  4517                              <1> 	;	
  4518                              <1> 	; Retro UNIX 8086 v1 modification:
  4519                              <1> 	;	The user/application program puts breakpoint address
  4520                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4521                              <1> 	; 	(argument transfer method 1)
  4522                              <1> 	;
  4523                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4524                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4525                              <1> 	;  NOTE:
  4526                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4527                              <1> 	;	'u.break' address) of user's memory for original unix's
  4528                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4529                              <1> 
  4530                              <1> 		; mov u.break,r1 / move users break point to r1
  4531                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4532                              <1> 		; blos 1f / yes, 1f
  4533                              <1> 	; 23/06/2015
  4534 00004EDD 8B2D[68710000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4535                              <1> 	;and	ebp, ebp
  4536                              <1> 	;jz	short sysbreak_3 
  4537                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4538                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4539 00004EE3 8B15[2C710000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4540 00004EE9 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4541                              <1> 	; 07/10/2015
  4542 00004EEC 891D[68710000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4543                              <1> 	;
  4544 00004EF2 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4545                              <1> 			   ; with top of user's stack (virtual!)
  4546 00004EF4 7327                <1> 	jnb	short sysbreak_3
  4547                              <1> 		; cmp r1,sp / is it the same or higher 
  4548                              <1> 			  ; / than the stack?
  4549                              <1> 		; bhis 1f / yes, 1f
  4550 00004EF6 89DE                <1> 	mov	esi, ebx
  4551 00004EF8 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4552 00004EFA 7621                <1> 	jna	short sysbreak_3 
  4553                              <1> 	;push	ebx
  4554                              <1> sysbreak_1:
  4555 00004EFC 89EB                <1> 	mov	ebx, ebp  
  4556 00004EFE E859E4FFFF          <1> 	call	get_physical_addr ; get physical address
  4557 00004F03 0F828CFEFFFF        <1> 	jc	tr_addr_nm_err
  4558                              <1> 	; 18/10/2015
  4559 00004F09 89C7                <1> 	mov	edi, eax 
  4560 00004F0B 29C0                <1> 	sub	eax, eax ; 0
  4561                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4562 00004F0D 39CE                <1> 	cmp	esi, ecx
  4563 00004F0F 7302                <1> 	jnb	short sysbreak_2
  4564 00004F11 89F1                <1> 	mov	ecx, esi
  4565                              <1> sysbreak_2:
  4566 00004F13 29CE                <1> 	sub	esi, ecx
  4567 00004F15 01CD                <1> 	add	ebp, ecx
  4568 00004F17 F3AA                <1> 	rep 	stosb
  4569 00004F19 09F6                <1> 	or	esi, esi
  4570 00004F1B 75DF                <1> 	jnz	short sysbreak_1
  4571                              <1> 	;
  4572                              <1> 		; bit $1,r1 / is it an odd address
  4573                              <1> 		; beq 2f / no, its even
  4574                              <1> 		; clrb (r1)+ / yes, make it even
  4575                              <1> 	; 2: / clear area between the break point and the stack
  4576                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4577                              <1> 		; bhis 1f / yes, quit
  4578                              <1> 		; clr (r1)+ / clear word
  4579                              <1> 		; br 2b / go back
  4580                              <1> 	;pop	ebx
  4581                              <1> sysbreak_3: ; 1:
  4582                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4583                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4584                              <1> 			; / in u.break (set new break point)
  4585                              <1> 		; br sysret4 / br sysret
  4586 00004F1D E9C5EDFFFF          <1> 	jmp	sysret
  4587                              <1> 
  4588                              <1> 
  4589                              <1> maknod: 
  4590                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4591                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4592                              <1> 	;
  4593                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4594                              <1> 	; for this i-node in the current directory.
  4595                              <1> 	;
  4596                              <1> 	; INPUTS ->
  4597                              <1> 	;    r1 - contains mode
  4598                              <1> 	;    ii - current directory's i-number	
  4599                              <1> 	;    	
  4600                              <1> 	; OUTPUTS ->
  4601                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4602                              <1> 	;    i.flgs - flags in new i-node 
  4603                              <1> 	;    i.uid - filled with u.uid
  4604                              <1> 	;    i.nlks - 1 is put in the number of links
  4605                              <1> 	;    i.ctim - creation time				
  4606                              <1> 	;    i.ctim+2 - modification time
  4607                              <1> 	;    imod - set via call to setimod
  4608                              <1> 	;	
  4609                              <1> 	; ((AX = R1)) input
  4610                              <1> 	;
  4611                              <1> 	; (Retro UNIX Prototype : 
  4612                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4613                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4614                              <1> 
  4615                              <1> 	; / r1 contains the mode
  4616 00004F22 80CC80              <1> 	or 	ah, 80h  ; 10000000b
  4617                              <1> 		; bis	$100000,r1 / allocate flag set
  4618 00004F25 6650                <1> 	push	ax
  4619                              <1> 		; mov r1,-(sp) / put mode on stack
  4620                              <1> 	; 31/07/2013
  4621 00004F27 66A1[10710000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4622                              <1> 		; mov ii,r1 / move current i-number to r1
  4623 00004F2D B201                <1> 	mov	dl, 1 ; owner flag mask
  4624 00004F2F E89A070000          <1> 	call	access	
  4625                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4626 00004F34 6650                <1> 	push	ax
  4627                              <1> 		; mov r1,-(sp) / put i-number on stack
  4628 00004F36 66B82800            <1> 	mov	ax, 40
  4629                              <1> 		; mov $40.,r1 / r1 = 40
  4630                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4631 00004F3A 6640                <1> 	inc	ax
  4632                              <1> 		; inc r1 / r1 = r1 + 1
  4633 00004F3C E8DB080000          <1> 	call	imap
  4634                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4635                              <1> 			    ; /	inode map in r2 & m
  4636                              <1>           ; DX (MQ) has a 1 in the calculated bit position
  4637                              <1>           ; eBX (R2) has byte address of the byte with allocation bit
  4638                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4639                              <1> 	;	       Inode count must be checked here
  4640                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4641 00004F41 8413                <1> 	test	[ebx], dl
  4642                              <1> 		; bitb mq,(r2) / is the i-node active
  4643 00004F43 75F5                <1> 	jnz	short maknod1
  4644                              <1> 		; bne 1b / yes, try the next one
  4645 00004F45 0813                <1> 	or	[ebx], dl
  4646                              <1> 		; bisb mq,(r2) / no, make it active 
  4647                              <1> 			     ; / (put a 1 in the bit map)
  4648 00004F47 E89B060000          <1> 	call	iget
  4649                              <1> 		; jsr r0,iget / get i-node into core
  4650 00004F4C 66F705[D06D0000]00- <1> 	test	word [i.flgs], 8000h 
  4650 00004F54 80                  <1>
  4651                              <1> 		; tst i.flgs / is i-node already allocated
  4652 00004F55 75E3                <1> 	jnz	short maknod1	
  4653                              <1> 		; blt 1b / yes, look for another one
  4654 00004F57 66A3[70710000]      <1> 	mov	[u.dirbuf], ax
  4655                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4656 00004F5D 6658                <1> 	pop	ax
  4657                              <1> 		; mov (sp)+,r1 / get current i-number back
  4658 00004F5F E883060000          <1> 	call	iget
  4659                              <1> 		; jsr r0,iget / get i-node in core
  4660 00004F64 E865F7FFFF          <1> 	call	mkdir
  4661                              <1> 		; jsr r0,mkdir / make a directory entry 
  4662                              <1> 			     ; / in current directory
  4663 00004F69 66A1[70710000]      <1> 	mov	ax, [u.dirbuf]
  4664                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4665 00004F6F E873060000          <1> 	call	iget
  4666                              <1> 		; jsr r0,iget / get it into core
  4667                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4668 00004F74 B908000000          <1> 	mov	ecx, 8 
  4669 00004F79 31C0                <1> 	xor	eax, eax ; 0
  4670 00004F7B BF[D06D0000]        <1> 	mov	edi, inode 
  4671 00004F80 F3AB                <1> 	rep	stosd
  4672                              <1> 	;
  4673 00004F82 668F05[D06D0000]    <1> 	pop	word [i.flgs]
  4674                              <1> 		; mov (sp)+,i.flgs / fill flags
  4675 00004F89 8A0D[8A710000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4676 00004F8F 880D[D46D0000]      <1> 	mov 	[i.uid], cl
  4677                              <1> 		; movb u.uid,i.uid / user id	
  4678 00004F95 C605[D26D0000]01    <1> 	mov     byte [i.nlks], 1
  4679                              <1> 		; movb $1,i.nlks / 1 link
  4680                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4681                              <1> 	;mov	eax, [s.time]
  4682                              <1> 	;mov 	[i.ctim], eax
  4683                              <1> 	 	; mov s.time,i.ctim / time created
  4684                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4685                              <1> 	; Retro UNIX 8086 v1 modification !
  4686                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4687                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4688 00004F9C E8E2070000          <1> 	call setimod
  4689                              <1> 		; jsr r0,setimod / set modified flag
  4690 00004FA1 C3                  <1> 	retn
  4691                              <1> 		; rts r0 / return
  4692                              <1> 
  4693                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4694                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4695                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4696                              <1> 	;
  4697                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4698                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4699                              <1> 	; The file descriptor refers to a file open for reading or
  4700                              <1> 	; writing. The read (or write) pointer is set as follows:
  4701                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4702                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4703                              <1> 	;	  current location plus offset.
  4704                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4705                              <1> 	;	  size of file plus offset.
  4706                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4707                              <1> 	;
  4708                              <1> 	; Calling sequence:
  4709                              <1> 	;	sysseek; offset; ptrname
  4710                              <1> 	; Arguments:
  4711                              <1> 	;	offset - number of bytes desired to move 
  4712                              <1> 	;		 the r/w pointer
  4713                              <1> 	;	ptrname - a switch indicated above
  4714                              <1> 	;
  4715                              <1> 	; Inputs: r0 - file descriptor 
  4716                              <1> 	; Outputs: -
  4717                              <1> 	; ...............................................................
  4718                              <1> 	;	
  4719                              <1> 	; Retro UNIX 8086 v1 modification: 
  4720                              <1> 	;       'sysseek' system call has three arguments; so,
  4721                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4722                              <1> 	;	* 2nd argument, offset is in CX register
  4723                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4724                              <1> 	;	
  4725                              <1> 
  4726 00004FA2 E823000000          <1> 	call	seektell
  4727                              <1> 	; AX = u.count
  4728                              <1> 	; BX = *u.fofp
  4729                              <1> 		; jsr r0,seektell / get proper value in u.count
  4730                              <1> 		; add u.base,u.count / add u.base to it
  4731 00004FA7 0305[5C710000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4732 00004FAD 8903                <1> 	mov	[ebx], eax
  4733                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4734 00004FAF E933EDFFFF          <1> 	jmp	sysret
  4735                              <1> 		; br sysret4
  4736                              <1> 
  4737                              <1> systell: ; / get the r/w pointer
  4738                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4739                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4740                              <1> 	;
  4741                              <1> 	; Retro UNIX 8086 v1 modification:
  4742                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4743                              <1> 	; 	    it returns with error !
  4744                              <1> 	; Inputs: r0 - file descriptor 
  4745                              <1> 	; Outputs: r0 - file r/w pointer
  4746                              <1> 
  4747                              <1> 	;xor	ecx, ecx ; 0
  4748 00004FB4 BA01000000          <1> 	mov	edx, 1 ; 05/08/2013
  4749                              <1> 	;call 	seektell
  4750 00004FB9 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4751                              <1> 	;mov	ebx, [u.fofp]
  4752 00004FBE 8B03                <1> 	mov	eax, [ebx]
  4753 00004FC0 A3[34710000]        <1> 	mov	[u.r0], eax
  4754 00004FC5 E91DEDFFFF          <1> 	jmp	sysret
  4755                              <1> 
  4756                              <1> ; Original unix v1 'systell' system call:
  4757                              <1> 		; jsr r0,seektell
  4758                              <1> 		; br error4
  4759                              <1> 
  4760                              <1> seektell:
  4761                              <1> 	; 03/01/2016
  4762                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4763                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4764                              <1> 	;
  4765                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4766                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4767                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4768                              <1> 	; getf. The i-node is brought into core and then u.count
  4769                              <1> 	; is checked to see it is a 0, 1, or 2.
  4770                              <1> 	; If it is 0 - u.count stays the same
  4771                              <1> 	;          1 - u.count = offset (u.fofp)
  4772                              <1> 	;	   2 - u.count = i.size (size of file)
  4773                              <1> 	; 	 		
  4774                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4775                              <1> 	;	Argument 1, file descriptor is in BX;
  4776                              <1> 	;	Argument 2, offset is in CX;
  4777                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4778                              <1> 	;
  4779                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4780                              <1> 	; call 	arg
  4781                              <1> 	;
  4782                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4783                              <1> 	;
  4784 00004FCA 890D[5C710000]      <1> 	mov 	[u.base], ecx ; offset
  4785                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4786                              <1> seektell0:
  4787 00004FD0 8915[60710000]      <1> 	mov 	[u.count], edx
  4788                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4789                              <1> 	; mov	ax, bx
  4790                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4791                              <1> 			     ; / (index in u.fp list)
  4792                              <1> 	; call	getf
  4793                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4794                              <1> 	; BX = file descriptor (file number)
  4795 00004FD6 E80EFCFFFF          <1> 	call	getf1
  4796 00004FDB 6609C0              <1> 	or	ax, ax ; i-number of the file
  4797                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4798                              <1> 		             ; / put it on the stack
  4799                              <1> 	;jz	error
  4800                              <1> 		; beq error4 / if i-number is 0, not active so error
  4801 00004FDE 750F                <1> 	jnz	short seektell1
  4802 00004FE0 C705[AC710000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4802 00004FE8 0000                <1>
  4803 00004FEA E9D8ECFFFF          <1> 	jmp	error
  4804                              <1> seektell1:
  4805                              <1> 	;push	eax
  4806 00004FEF 80FC80              <1> 	cmp	ah, 80h
  4807 00004FF2 7203                <1> 	jb	short seektell2
  4808                              <1> 		; bgt .+4 / if its positive jump
  4809 00004FF4 66F7D8              <1> 	neg	ax
  4810                              <1> 		; neg r1 / if not make it positive
  4811                              <1> seektell2:
  4812 00004FF7 E8EB050000          <1> 	call	iget
  4813                              <1> 		; jsr r0,iget / get its i-node into core
  4814 00004FFC 8B1D[48710000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4815 00005002 803D[60710000]01    <1> 	cmp	byte [u.count], 1
  4816                              <1> 		; cmp u.count,$1 / is ptr name =1
  4817 00005009 7705                <1> 	ja	short seektell3
  4818                              <1> 		; blt 2f / no its zero
  4819 0000500B 740A                <1> 	je	short seektell_4
  4820                              <1> 		; beq 1f / yes its 1
  4821 0000500D 31C0                <1> 	xor	eax, eax
  4822                              <1> 	;jmp	short seektell_5
  4823 0000500F C3                  <1> 	retn
  4824                              <1> seektell3:
  4825                              <1> 	; 03/01/2016
  4826                              <1> 	;movzx	eax, word [i.size]
  4827 00005010 66A1[D86D0000]      <1>         mov   	ax, [i.size]
  4828                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4829                              <1>                                    ; / in file in u.count
  4830                              <1> 	;jmp	short seektell_5
  4831                              <1> 		; br 2f
  4832 00005016 C3                  <1> 	retn
  4833                              <1> seektell_4: ; 1: / ptrname =1
  4834                              <1> 	;mov	ebx, [u.fofp]
  4835 00005017 8B03                <1> 	mov	eax, [ebx]
  4836                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4837                              <1> ;seektell_5: ; 2: / ptrname =0
  4838                              <1> 	;mov	[u.count], eax
  4839                              <1> 	;pop	eax 
  4840                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4841 00005019 C3                  <1> 	retn
  4842                              <1> 		; rts r0
  4843                              <1> 
  4844                              <1> sysintr: ; / set interrupt handling
  4845                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4846                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4847                              <1> 	;
  4848                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4849                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4850                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4851                              <1> 	; If one does the interrupt character in the tty buffer is
  4852                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4853                              <1> 	; 'sysret' is just called.	
  4854                              <1> 	;
  4855                              <1> 	; Calling sequence:
  4856                              <1> 	;	sysintr; arg
  4857                              <1> 	; Argument:
  4858                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4859                              <1> 	;	    - if 1, intterupts cause their normal result
  4860                              <1> 	;		 i.e force an exit.
  4861                              <1> 	;	    - if arg is a location within the program,
  4862                              <1> 	;		control is passed to that location when
  4863                              <1> 	;		an interrupt occurs.	
  4864                              <1> 	; Inputs: -
  4865                              <1> 	; Outputs: -
  4866                              <1> 	; ...............................................................
  4867                              <1> 	;	
  4868                              <1> 	; Retro UNIX 8086 v1 modification: 
  4869                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4870                              <1> 	;	then branches into sysquit.
  4871                              <1> 	;
  4872 0000501A 66891D[84710000]    <1> 	mov	[u.intr], bx
  4873                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4874                              <1> 		; br 1f / go into quit routine
  4875 00005021 E9C1ECFFFF          <1> 	jmp	sysret
  4876                              <1> 
  4877                              <1> sysquit:
  4878                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4879                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4880                              <1> 	;
  4881                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4882                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4883                              <1> 	; tty exists. If one does the interrupt character in the tty
  4884                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4885                              <1> 	; 'sysret' is just called.	
  4886                              <1> 	;
  4887                              <1> 	; Calling sequence:
  4888                              <1> 	;	sysquit; arg
  4889                              <1> 	; Argument:
  4890                              <1> 	;	arg - if 0, this call diables quit signals from the
  4891                              <1> 	;		typewriter (ASCII FS)
  4892                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4893                              <1> 	;		cease and a core image to be produced.
  4894                              <1> 	;		 i.e force an exit.
  4895                              <1> 	;	    - if arg is an addres in the program,
  4896                              <1> 	;		a quit causes control to sent to that
  4897                              <1> 	;		location.	
  4898                              <1> 	; Inputs: -
  4899                              <1> 	; Outputs: -
  4900                              <1> 	; ...............................................................
  4901                              <1> 	;	
  4902                              <1> 	; Retro UNIX 8086 v1 modification: 
  4903                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4904                              <1> 	;	then branches into 'sysret'.
  4905                              <1> 	;
  4906 00005026 66891D[86710000]    <1> 	mov	[u.quit], bx
  4907 0000502D E9B5ECFFFF          <1> 	jmp	sysret
  4908                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4909                              <1> 	;1:
  4910                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4911                              <1> 			      ; / to r1
  4912                              <1> 		; beq sysret4 / return to user
  4913                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4914                              <1> 			   ; / in the tty buffer
  4915                              <1> 		; br sysret4 / return to user
  4916                              <1> 
  4917                              <1> syssetuid: ; / set process id
  4918                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4919                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4920                              <1> 	;
  4921                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4922                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4923                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4924                              <1> 	; Only the super user can make this call.	
  4925                              <1> 	;
  4926                              <1> 	; Calling sequence:
  4927                              <1> 	;	syssetuid
  4928                              <1> 	; Arguments: -
  4929                              <1> 	;
  4930                              <1> 	; Inputs: (u.r0) - contains the process id.
  4931                              <1> 	; Outputs: -
  4932                              <1> 	; ...............................................................
  4933                              <1> 	;	
  4934                              <1> 	; Retro UNIX 8086 v1 modification: 
  4935                              <1> 	;       BL contains the (new) user ID of the current process
  4936                              <1> 
  4937                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4938 00005032 3A1D[8C710000]      <1> 	cmp	bl, [u.ruid] 
  4939                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4940                              <1> 			       ; / id number
  4941 00005038 741E                <1> 	je	short setuid1
  4942                              <1> 		; beq 1f / yes
  4943 0000503A 803D[8A710000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4944                              <1> 		; tstb u.uid / no, is current user the super user?
  4945                              <1> 	;ja	error
  4946                              <1> 		; bne error4 / no, error
  4947 00005041 760F                <1> 	jna	short setuid0
  4948 00005043 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4948 0000504B 0000                <1>
  4949                              <1> 				;  'permission denied !' error
  4950 0000504D E975ECFFFF          <1> 	jmp	error
  4951                              <1> setuid0:
  4952 00005052 881D[8C710000]      <1> 	mov	[u.ruid], bl
  4953                              <1> setuid1: ; 1:
  4954 00005058 881D[8A710000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4955                              <1> 		; movb r1,u.uid / put process id in u.uid
  4956                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4957 0000505E E984ECFFFF          <1> 	jmp	sysret
  4958                              <1> 		; br sysret4 / system return
  4959                              <1> 
  4960                              <1> sysgetuid: ; < get user id >
  4961                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4962                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4963                              <1> 	;
  4964                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4965                              <1> 	; The real user ID identifies the person who is logged in,
  4966                              <1> 	; in contradistinction to the effective user ID, which
  4967                              <1> 	; determines his access permission at each moment. It is thus
  4968                              <1> 	; useful to programs which operate using the 'set user ID'
  4969                              <1> 	; mode, to find out who invoked them.	
  4970                              <1> 	;
  4971                              <1> 	; Calling sequence:
  4972                              <1> 	;	syssetuid
  4973                              <1> 	; Arguments: -
  4974                              <1> 	;
  4975                              <1> 	; Inputs: -
  4976                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4977                              <1> 	; ...............................................................
  4978                              <1> 	;	
  4979                              <1> 	; Retro UNIX 8086 v1 modification: 
  4980                              <1> 	;       AL contains the real user ID at return.
  4981                              <1> 	;
  4982 00005063 0FB605[8C710000]    <1> 	movzx 	eax, byte [u.ruid]
  4983 0000506A A3[34710000]        <1> 	mov	[u.r0], eax
  4984                              <1> 		; movb u.ruid,*u.r0 / move the real user id to (u.r0)
  4985 0000506F E973ECFFFF          <1> 	jmp	sysret
  4986                              <1> 		; br sysret4 / system return, sysret
  4987                              <1> 
  4988                              <1> anyi: 
  4989                              <1> 	; 27/12/2021 (Retro UNIX 386 v1.2)
  4990                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  4991                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4992                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4993                              <1> 	;
  4994                              <1> 	; 'anyi' is called if a file deleted while open.
  4995                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4996                              <1> 	;
  4997                              <1> 	; INPUTS ->
  4998                              <1> 	;    r1 - contains an i-number
  4999                              <1> 	;    fsp - start of table containing open files
  5000                              <1> 	;
  5001                              <1> 	; OUTPUTS ->
  5002                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  5003                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  5004                              <1> 	;    if file not found - bit in i-node map is cleared
  5005                              <1> 	;    			 (i-node is freed)
  5006                              <1> 	;               all blocks related to i-node are freed
  5007                              <1> 	;	        all flags in i-node are cleared
  5008                              <1> 	; ((AX = R1)) input
  5009                              <1> 	;
  5010                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  5011                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  5012                              <1> 	;
  5013                              <1> 		; / r1 contains an i-number
  5014 00005074 BB[D06D0000]        <1> 	mov	ebx, fsp
  5015                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  5016                              <1> anyi_1: ; 1:
  5017 00005079 663B03              <1> 	cmp	ax, [ebx]
  5018                              <1> 		; cmp r1,(r2) / do i-numbers match?
  5019 0000507C 7423                <1> 	je	short anyi_3
  5020                              <1> 		; beq 1f / yes, 1f
  5021                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5022                              <1> 	;neg	ax
  5023                              <1> 	;	; neg r1 / no complement r1
  5024                              <1> 	;cmp	ax, [ebx]
  5025                              <1> 	;	; cmp r1,(r2) / do they match now?
  5026                              <1> 	;je	short anyi_3
  5027                              <1> 		; beq 1f / yes, transfer
  5028                              <1> 		; / i-numbers do not match
  5029                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5030 0000507E 83C310              <1> 	add	ebx, fp.size ; runix v2 fsp table size is 16 bytes
  5031                              <1> 	;add	ebx, 10 ; fsp table size is 10 bytes
  5032                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  5033                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  5034                              <1> 	; 22/11/2021
  5035 00005081 81FB[F0700000]      <1> 	cmp	ebx, fsp + (NFILES*fp.size) ; fsp+(NFILES*16)
  5036                              <1> 	;cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  5037                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  5038                              <1> 			; / are we at last entry in the table
  5039 00005087 72F0                <1> 	jb	short anyi_1
  5040                              <1> 		; blt 1b / no, check next entries i-number
  5041                              <1> 	; 27/12/2021
  5042                              <1> 	;;cmp	ax, 32768
  5043                              <1> 	;cmp	ah, 80h ; negative number check
  5044                              <1> 	;	; tst r1 / yes, no match
  5045                              <1> 	;	; bge .+4
  5046                              <1> 	;jb	short anyi_2
  5047                              <1> 	;neg	ax
  5048                              <1> 	;	; neg r1 / make i-number positive
  5049                              <1> ;anyi_2:	
  5050 00005089 E88E070000          <1> 	call	imap
  5051                              <1> 		; jsr r0,imap / get address of allocation bit 
  5052                              <1> 			    ; / in the i-map in r2
  5053                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  5054                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  5055                              <1>  	; not	dx
  5056 0000508E F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  5057                              <1>         ;and	[ebx], dx
  5058 00005090 2013                <1> 	and 	[ebx], dl 
  5059                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  5060 00005092 E80E070000          <1> 	call	itrunc
  5061                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  5062 00005097 66C705[D06D0000]00- <1>  	mov 	word [i.flgs], 0
  5062 0000509F 00                  <1>
  5063                              <1> 		; clr i.flgs / clear all flags in the i-node
  5064 000050A0 C3                  <1> 	retn
  5065                              <1> 		;rts	r0 / return
  5066                              <1> anyi_3: ; 1: / i-numbers match
  5067                              <1> 	; 27/12/2021 - Retro UNIX 386 v1.2 (runix v2 fs)
  5068 000050A1 804B0580            <1> 	or	byte [ebx+5], 80h ; set deleted file flag (bit 7)
  5069                              <1> 	; 22/06/2015
  5070                              <1> 	;inc 	byte [ebx+9]
  5071                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  5072                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  5073 000050A5 C3                  <1> 	retn
  5074                              <1> 		; rts r0
  2022                                  %include 'u3.s'      ; 10/05/2015
  2023                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2024                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2025                              <1> ; ****************************************************************************
  2026                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS3.INC
  2027                              <1> ; Last Modification: 24/12/2021
  2028                              <1> ; ----------------------------------------------------------------------------
  2029                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2030                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2031                              <1> ;
  2032                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2033                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2034                              <1> ; <Bell Laboratories (17/3/1972)>
  2035                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2036                              <1> ;
  2037                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2038                              <1> ;
  2039                              <1> ; ****************************************************************************
  2040                              <1> 
  2041                              <1> tswitch: ; Retro UNIX 386 v1
  2042                              <1> tswap:
  2043                              <1> 	; 01/09/2015
  2044                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2045                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2046                              <1> 	; time out swap, called when a user times out.
  2047                              <1> 	; the user is put on the low priority queue.
  2048                              <1> 	; This is done by making a link from the last user
  2049                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2050                              <1> 	; then he is swapped out.
  2051                              <1> 	;
  2052                              <1> 	; Retro UNIX 386 v1 modification ->
  2053                              <1> 	;       swap (software task switch) is performed by changing
  2054                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2055                              <1> 	;	as in Retro UNIX 8086 v1.
  2056                              <1> 	;
  2057                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2058                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2059                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2060                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2061                              <1> 	;	compatibles was using 1MB segmented memory 
  2062                              <1> 	;	in 8086/8088 times.
  2063                              <1> 	;
  2064                              <1> 	; INPUTS ->
  2065                              <1> 	;    u.uno - users process number
  2066                              <1> 	;    runq+4 - lowest priority queue
  2067                              <1> 	; OUTPUTS ->
  2068                              <1> 	;    r0 - users process number
  2069                              <1> 	;    r2 - lowest priority queue address
  2070                              <1> 	;
  2071                              <1> 	; ((AX = R0, BX = R2)) output
  2072                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2073                              <1> 	;
  2074 000050A6 A0[89710000]        <1> 	mov 	al, [u.uno]
  2075                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2076                              <1> 		; mov  $runq+4,r2 
  2077                              <1> 			; / move lowest priority queue address to r2
  2078 000050AB E8CD000000          <1>         call 	putlu
  2079                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2080                              <1> 		             ; / u.uno's user
  2081                              <1> 
  2082                              <1> switch: ; Retro UNIX 386 v1
  2083                              <1> swap:
  2084                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2085                              <1> 	; 02/09/2015
  2086                              <1> 	; 01/09/2015
  2087                              <1> 	; 31/08/2015
  2088                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2089                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2090                              <1> 	; 'swap' is routine that controls the swapping of processes
  2091                              <1> 	; in and out of core.
  2092                              <1> 	;
  2093                              <1> 	; Retro UNIX 386 v1 modification ->
  2094                              <1> 	;       swap (software task switch) is performed by changing
  2095                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2096                              <1> 	;	as in Retro UNIX 8086 v1.
  2097                              <1> 	;
  2098                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2099                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2100                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2101                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2102                              <1> 	;	compatibles was using 1MB segmented memory 
  2103                              <1> 	;	in 8086/8088 times.
  2104                              <1> 	;
  2105                              <1> 	; INPUTS ->
  2106                              <1> 	;    runq table - contains processes to run.
  2107                              <1> 	;    p.link - contains next process in line to be run.
  2108                              <1> 	;    u.uno - process number of process in core	
  2109                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2110                              <1> 	; OUTPUTS ->
  2111                              <1> 	;    (original unix v1 -> present process to its disk block)
  2112                              <1> 	;    (original unix v1 -> new process into core -> 
  2113                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2114                              <1> 	;	   for new process)
  2115                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2116                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2117                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2118                              <1> 	;	 for now, it will swap the process if there is not
  2119                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2120                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2121                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2122                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2123                              <1> 	;
  2124                              <1> 	;    u.pri -points to highest priority run Q.
  2125                              <1> 	;    r2 - points to the run queue.
  2126                              <1> 	;    r1 - contains new process number
  2127                              <1> 	;    r0 - points to place in routine or process that called
  2128                              <1> 	;	  swap all user parameters
  2129                              <1> 	;				
  2130                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2131                              <1> 	;
  2132                              <1> swap_0:
  2133                              <1> 		;mov $300,*$ps / processor priority = 6
  2134 000050B0 BE[24710000]        <1> 	mov	esi, runq
  2135                              <1> 		; mov $runq,r2 / r2 points to runq table
  2136                              <1> swap_1: ; 1: / search runq table for highest priority process
  2137 000050B5 668B06              <1> 	mov	ax, [esi]
  2138 000050B8 6621C0              <1> 	and 	ax, ax
  2139                              <1>        		; tst (r2)+ / are there any processes to run 
  2140                              <1> 			  ; / in this Q entry
  2141 000050BB 7507                <1> 	jnz	short swap_2
  2142                              <1>        		; bne 1f / yes, process 1f
  2143                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2144                              <1> 			       ; / to end of table
  2145                              <1> 		; bne 1b / if not at end, go back
  2146 000050BD E8E0000000          <1> 	call	idle
  2147                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2148                              <1> 				       ; / all queues are empty
  2149 000050C2 EBF1                <1> 	jmp	short swap_1
  2150                              <1> 		; br swap
  2151                              <1> swap_2: ; 1:
  2152 000050C4 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2153                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2154                              <1>  		; mov r2,u.pri / set present user to this run queue
  2155                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2156 000050C7 38E0                <1> 	cmp	al, ah
  2157                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2158                              <1> 			      ; / in this Q to be run
  2159 000050C9 740A                <1> 	je	short swap_3
  2160                              <1>        		; beq 1f / yes
  2161                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2162                              <1> 	;movzx	ebx, al
  2163 000050CB 8AA3[8F6E0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2164 000050D1 8826                <1>        	mov	[esi], ah
  2165                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2166                              <1> 				       ; / in line into run queue
  2167 000050D3 EB05                <1> 	jmp	short swap_4
  2168                              <1>        		; br 2f
  2169                              <1> swap_3: ; 1:
  2170                              <1> 	;xor	dx, dx
  2171                              <1> 	; 24/12/2021
  2172 000050D5 31D2                <1> 	xor	edx, edx
  2173 000050D7 668916              <1> 	mov	[esi], dx
  2174                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2175                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2176                              <1>       ; / in new process if required
  2177                              <1>        		; clr *$ps / clear processor status
  2178 000050DA 8A25[89710000]      <1> 	mov 	ah, [u.uno]
  2179 000050E0 38C4                <1> 	cmp	ah, al
  2180                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2181                              <1> 			      ; / the process in core?
  2182 000050E2 743B                <1>        	je	short swap_8
  2183                              <1>        		; beq 2f / yes, don't have to swap
  2184                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2185                              <1> 			   ; / (address in routine that called swap)
  2186                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2187                              <1> 	; 01/09/2015
  2188                              <1> 	;mov	[u.usp], esp
  2189                              <1>        		; mov sp,u.usp / save stack pointer
  2190                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2191                              <1> 			       ; / to the stack pointer
  2192 000050E4 08E4                <1> 	or	ah, ah
  2193                              <1>        		; tstb u.uno / is the process # = 0
  2194 000050E6 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2195                              <1> 		; beq  1f / yes, kill process by overwriting
  2196                              <1> 	; 02/09/2015
  2197 000050E8 8925[30710000]      <1> 	mov	[u.usp], esp ; return  address for 'syswait' & 'sleep'
  2198                              <1> 	;
  2199 000050EE E834000000          <1> 	call	wswap
  2200                              <1> 		;jsr r0,wswap / write out core to disk
  2201                              <1> 	 ; 31/08/2015
  2202                              <1> 	;movzx	ebx, al ; New (running) process number
  2203 000050F3 EB1C                <1> 	jmp 	short swap_7
  2204                              <1> swap_6:
  2205                              <1> 	; 31/08/2015
  2206                              <1> 	; Deallocate memory pages belong to the process
  2207                              <1> 	; which is being terminated
  2208                              <1> 	; 14/05/2015 ('sysexit')
  2209                              <1>  	; Deallocate memory pages of the process
  2210                              <1> 	; (Retro UNIX 386 v1 modification !)
  2211                              <1> 	;
  2212                              <1> 	; movzx ebx, al
  2213 000050F5 53                  <1> 	push	ebx
  2214 000050F6 A1[98710000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2215 000050FB 8B1D[9C710000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2216 00005101 E89ADFFFFF          <1> 	call	deallocate_page_dir
  2217 00005106 A1[94710000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2218 0000510B E828E0FFFF          <1> 	call	deallocate_page
  2219 00005110 5B                  <1> 	pop	ebx
  2220                              <1> swap_7: ;1: 
  2221                              <1> 	; 02/09/2015
  2222                              <1> 	; 31/08/2015
  2223                              <1> 	; 14/05/2015
  2224 00005111 C0E302              <1> 	shl	bl, 2 ; * 4 
  2225 00005114 8B83[AC6E0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2226                              <1> 	;cli
  2227 0000511A E831000000          <1> 	call	rswap
  2228                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2229                              <1> 		; jsr r0,rswap / read new process into core
  2230                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2231                              <1> 			      ; / to his program to its normal
  2232                              <1> 	; 01/09/2015
  2233                              <1> 	;mov	esp, [u.usp]	
  2234                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2235                              <1> 			     ; / new process stack
  2236                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2237                              <1> 			     ; / that just got swapped in, left off.,
  2238                              <1> 			     ; / i.e., transfer control to new process
  2239                              <1> 	;sti
  2240                              <1> swap_8: ;2:
  2241                              <1> 	; RETRO UNIX 8086 v1 modification !
  2242 0000511F C605[80710000]04    <1> 	mov	byte [u.quant], time_count 
  2243                              <1> 		; movb $30.,uquant / initialize process time quantum
  2244 00005126 C3                  <1> 	retn
  2245                              <1> 		; rts r0 / return
  2246                              <1> 
  2247                              <1> wswap:  ; < swap out, swap to disk >
  2248                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2249                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2250                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2251                              <1> 	; appropriate disk area.
  2252                              <1> 	;
  2253                              <1> 	; Retro UNIX 386 v1 modification ->
  2254                              <1> 	;       User (u) structure content and the user's register content
  2255                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2256                              <1> 	;	saving 'u' structure and user registers for task switching).
  2257                              <1> 	;	u.usp - points to kernel stack address which contains
  2258                              <1> 	;		user's registers while entering system call.  
  2259                              <1> 	;	u.sp  - points to kernel stack address 
  2260                              <1> 	;		to return from system call -for IRET-.
  2261                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2262                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2263                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2264                              <1> 	;
  2265                              <1> 	; Retro UNIX 8086 v1 modification ->
  2266                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2267                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2268                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2269                              <1> 	;	compatibles was using 1MB segmented memory 
  2270                              <1> 	;	in 8086/8088 times.
  2271                              <1> 	;
  2272                              <1> 	; INPUTS ->
  2273                              <1> 	;    u.break - points to end of program
  2274                              <1> 	;    u.usp - stack pointer at the moment of swap
  2275                              <1> 	;    core - beginning of process program		
  2276                              <1> 	;    ecore - end of core 	
  2277                              <1> 	;    user - start of user parameter area		
  2278                              <1> 	;    u.uno - user process number	
  2279                              <1> 	;    p.dska - holds block number of process	
  2280                              <1> 	; OUTPUTS ->
  2281                              <1> 	;    swp I/O queue
  2282                              <1> 	;    p.break - negative word count of process 
  2283                              <1> 	;    r1 - process disk address	
  2284                              <1> 	;    r2 - negative word count
  2285                              <1> 	;
  2286                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2287                              <1> 	;
  2288                              <1> 	; INPUTS ->
  2289                              <1> 	;    u.uno - process number (to be swapped out)
  2290                              <1> 	; OUTPUTS ->
  2291                              <1> 	;    none
  2292                              <1> 	;
  2293                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2294                              <1> 	;
  2295 00005127 8B3D[94710000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2296 0000512D B931000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2297 00005132 BE[2C710000]        <1> 	mov	esi, user ; active user (u) structure	
  2298 00005137 F3A5                <1> 	rep	movsd
  2299                              <1> 	;
  2300 00005139 8B35[30710000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2301                              <1> 			     ;      points to user registers)
  2302 0000513F 8B0D[2C710000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2303                              <1> 			     ; (for IRET)
  2304                              <1> 			     ; [u.sp] -> EIP (user)
  2305                              <1> 			     ; [u.sp+4]-> CS (user)
  2306                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2307                              <1> 			     ; [u.sp+12] -> ESP (user)
  2308                              <1> 			     ; [u.sp+16] -> SS (user)	
  2309 00005145 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2310 00005147 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2311                              <1> 			     ; (for IRET) 	
  2312 0000514A C1E902              <1> 	shr	ecx, 2	     		
  2313 0000514D F3A5                <1> 	rep	movsd
  2314 0000514F C3                  <1> 	retn
  2315                              <1> 
  2316                              <1> 	; Original UNIX v1 'wswap' routine:
  2317                              <1> 	; wswap:
  2318                              <1> 		; mov *$30,u.emt / determines handling of emts
  2319                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2320                              <1> 				; / illegal instructions
  2321                              <1> 		; mov u.break,r2 / put process program break address in r2
  2322                              <1> 		; inc r2 / add 1 to it 
  2323                              <1> 		; bic $1,r2 / make it even
  2324                              <1> 		; mov r2,u.break / set break to an even location
  2325                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2326                              <1> 			     ; / at moment of swap in r3
  2327                              <1> 		; cmp r2,$core / is u.break less than $core
  2328                              <1> 		; blos 2f / yes
  2329                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2330                              <1>        		; bhis 2f / yes
  2331                              <1> 	; 1:
  2332                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2333                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2334                              <1> 		; bne 1b / no, keep packing
  2335                              <1> 	 	; br 1f / yes
  2336                              <1> 	; 2:
  2337                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2338                              <1> 	; 1:
  2339                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2340                              <1> 			   ; / (user up to end of stack gets written out)
  2341                              <1> 		; neg r2 / make it negative
  2342                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2343                              <1> 		; mov r2,swp+4 / word count
  2344                              <1> 		; movb u.uno,r1 / move user process number to r1
  2345                              <1> 		; asl r1 / x2 for index
  2346                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2347                              <1> 				     ; / into the p.break table
  2348                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2349                              <1> 				    ; /	for process to r1
  2350                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2351                              <1> 			     ; / (block number)
  2352                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2353                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2354                              <1> 	; 1:
  2355                              <1>        		; tstb swp+1 / is lt done writing?
  2356                              <1>        		; bne 1b / no, wait
  2357                              <1> 		; rts r0 / yes, return to swap
  2358                              <1> 
  2359                              <1> rswap:  ; < swap in, swap from disk >
  2360                              <1> 	; 15/09/2015
  2361                              <1> 	; 28/08/2015
  2362                              <1> 	; 14/05/2015
  2363                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2364                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2365                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2366                              <1> 	; from disk into core.
  2367                              <1> 	;
  2368                              <1> 	; Retro UNIX 386 v1 modification ->
  2369                              <1> 	;       User (u) structure content and the user's register content
  2370                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2371                              <1> 	;	saving 'u' structure and user registers for task switching).
  2372                              <1> 	;	u.usp - points to kernel stack address which contains
  2373                              <1> 	;		user's registers while entering system call.  
  2374                              <1> 	;	u.sp  - points to kernel stack address 
  2375                              <1> 	;		to return from system call -for IRET-.
  2376                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2377                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2378                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2379                              <1> 	;
  2380                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2381                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2382                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2383                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2384                              <1> 	;	compatibles was using 1MB segmented memory 
  2385                              <1> 	;	in 8086/8088 times.
  2386                              <1> 	;
  2387                              <1> 	; INPUTS ->
  2388                              <1> 	;    r1 - process number of process to be read in
  2389                              <1> 	;    p.break - negative of word count of process 
  2390                              <1> 	;    p.dska - disk address of the process		
  2391                              <1> 	;    u.emt - determines handling of emt's 	
  2392                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2393                              <1> 	; OUTPUTS ->
  2394                              <1> 	;    8 = (u.ilgins)
  2395                              <1> 	;    24 = (u.emt)
  2396                              <1> 	;    swp - bit 10 is set to indicate read 
  2397                              <1> 	;		(bit 15=0 when reading is done)	
  2398                              <1> 	;    swp+2 - disk block address
  2399                              <1> 	;    swp+4 - negative word count 	
  2400                              <1> 	;      ((swp+6 - address of user structure)) 
  2401                              <1> 	;
  2402                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2403                              <1> 	;
  2404                              <1> 	; INPUTS ->
  2405                              <1> 	;    AL	- new process number (to be swapped in)	 
  2406                              <1> 	; OUTPUTS ->
  2407                              <1> 	;    none
  2408                              <1> 	;
  2409                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2410                              <1> 	;
  2411                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2412 00005150 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2413 00005152 B931000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2414 00005157 BF[2C710000]        <1> 	mov	edi, user ; active user (u) structure	
  2415 0000515C F3A5                <1> 	rep	movsd
  2416 0000515E 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2417 0000515F 8B3D[30710000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2418                              <1> 			     ;      points to user registers)
  2419 00005165 8B0D[2C710000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2420                              <1> 			     ; (for IRET)
  2421                              <1> 			     ; [u.sp] -> EIP (user)
  2422                              <1> 			     ; [u.sp+4]-> CS (user)
  2423                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2424                              <1> 			     ; [u.sp+12] -> ESP (user)
  2425                              <1> 			     ; [u.sp+16] -> SS (user)		
  2426                              <1> 	; 28/08/2015
  2427 0000516B 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2428 0000516D 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2429                              <1> 			     ; (for IRET) 	
  2430 00005170 C1E902              <1> 	shr	ecx, 2	       		
  2431 00005173 F3A5                <1> 	rep	movsd
  2432 00005175 8B25[30710000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2433 0000517B 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2434 0000517C C3                  <1> 	retn
  2435                              <1> 
  2436                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2437                              <1> 	;rswap:
  2438                              <1>        		; asl r1 / process number x2 for index
  2439                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2440                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2441                              <1>        		; bis $2000,swp / read
  2442                              <1>        		; jsr r0,ppoke / read it in 
  2443                              <1> 	; 1:
  2444                              <1>        		; tstb swp+1 / done
  2445                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2446                              <1>        		; mov u.emt,*$30 / yes move these
  2447                              <1>        		; mov u.ilgins,*$10 / back
  2448                              <1>        		; rts r0 / return
  2449                              <1> 
  2450                              <1> 	;unpack: ; / move stack back to its normal place
  2451                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2452                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2453                              <1> 		; blos 2f / yes, return
  2454                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2455                              <1> 			     ; / before swapping
  2456                              <1> 		; bhis 2f / yes, return
  2457                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2458                              <1> 		; add r3,r2
  2459                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2460                              <1> 	; 1:
  2461                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2462                              <1> 		; cmp r2,u.break / in core
  2463                              <1> 		; bne 1b
  2464                              <1> 	; 2:
  2465                              <1>        		; rts r0
  2466                              <1> 
  2467                              <1> putlu: 
  2468                              <1> 	; 12/09/2015
  2469                              <1> 	; 02/09/2015
  2470                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2471                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2472                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2473                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2474                              <1> 	; the last process on the queue to process in r1 by putting
  2475                              <1> 	; the process number in r1 into the last process's link.
  2476                              <1> 	;
  2477                              <1> 	; INPUTS ->
  2478                              <1> 	;    r1 - user process number
  2479                              <1> 	;    r2 - points to lowest priority queue 
  2480                              <1> 	;    p.dska - disk address of the process		
  2481                              <1> 	;    u.emt - determines handling of emt's 	
  2482                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2483                              <1> 	; OUTPUTS ->
  2484                              <1> 	;    r3 - process number of last process on the queue upon
  2485                              <1> 	;	  entering putlu
  2486                              <1> 	;    p.link-1 + r3 - process number in r1
  2487                              <1> 	;    r2 - points to lowest priority queue
  2488                              <1> 	;
  2489                              <1> 	; ((Modified registers: EDX, EBX)) 
  2490                              <1> 	;
  2491                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2492                              <1> 
  2493                              <1> 	; eBX = r2
  2494                              <1> 	; eAX = r1 (AL=r1b)
  2495                              <1> 
  2496 0000517D BB[24710000]        <1> 	mov	ebx, runq
  2497 00005182 0FB613              <1> 	movzx  	edx, byte [ebx]
  2498 00005185 43                  <1> 	inc	ebx
  2499 00005186 20D2                <1> 	and	dl, dl
  2500                              <1> 		; tstb (r2)+ / is queue empty?
  2501 00005188 740A                <1>        	jz	short putlu_1
  2502                              <1> 		; beq 1f / yes, branch
  2503 0000518A 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2504                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2505                              <1> 			     ; / in r3
  2506 0000518C 8882[8F6E0000]      <1>        	mov	[edx+p.link-1], al
  2507                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2508                              <1> 			     ; / "last users" link
  2509 00005192 EB03                <1> 	jmp	short putlu_2
  2510                              <1> 		; br 2f /
  2511                              <1> putlu_1: ; 1:
  2512 00005194 8843FF              <1> 	mov	[ebx-1], al
  2513                              <1>        		; movb r1,-1(r2) / user is only user; 
  2514                              <1> 			    ; / put process no. at beginning and at end
  2515                              <1> putlu_2: ; 2: 
  2516 00005197 8803                <1> 	mov	[ebx], al
  2517                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2518                              <1> 			     ; / on the queue
  2519 00005199 88C2                <1> 	mov	dl, al
  2520 0000519B 88B2[8F6E0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2521                              <1> 		; dec r2 / restore r2
  2522 000051A1 C3                  <1>         retn
  2523                              <1> 		; rts r0
  2524                              <1> 
  2525                              <1> ;copyz:
  2526                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2527                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2528                              <1> ;       mov     (r0)+,r1
  2529                              <1> ;       mov     (r0)+,r2
  2530                              <1> ;1:
  2531                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2532                              <1> ;       cmp     r1,r2 
  2533                              <1> ;       blo     1b
  2534                              <1> ;       mov     (sp)+,r2 / restore r2
  2535                              <1> ;       mov     (sp)+,r1 / restore r1
  2536                              <1> ;       rts     r0 
  2537                              <1> 
  2538                              <1> idle:
  2539                              <1> 	; 01/09/2015
  2540                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2541                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2542                              <1> 	; (idle & wait loop)
  2543                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2544                              <1> 	; idle procedure!
  2545                              <1>       	;
  2546                              <1>   	; 01/09/2015
  2547 000051A2 FB                  <1> 	sti
  2548                              <1>       	; 29/07/2013
  2549 000051A3 F4                  <1>       	hlt
  2550 000051A4 90                  <1>       	nop ; 10/10/2013
  2551 000051A5 90                  <1>       	nop
  2552 000051A6 90                  <1>       	nop
  2553                              <1>       	; 23/10/2013
  2554 000051A7 90                  <1>       	nop
  2555 000051A8 90                  <1>       	nop
  2556 000051A9 90                  <1>       	nop
  2557 000051AA 90                  <1>       	nop
  2558 000051AB C3                  <1>       	retn      
  2559                              <1> 
  2560                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2561                              <1> 	;clr *$ps / clear ps
  2562                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2563                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2564                              <1> 	;1 / wait for interrupt
  2565                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2566                              <1> 	;mov (sp)+,*$ps
  2567                              <1> 	;rts r0
  2568                              <1> 
  2569                              <1> clear:
  2570                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2571                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2572                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2573                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2574                              <1> 	; on the current device (cdev)
  2575                              <1> 	;	
  2576                              <1> 	; INPUTS ->
  2577                              <1> 	;    r1 - block number of block to be zeroed
  2578                              <1> 	;    cdev - current device number 
  2579                              <1> 	; OUTPUTS ->
  2580                              <1> 	;    a zeroed I/O buffer onto the current device
  2581                              <1> 	;    r1 - points to last entry in the I/O buffer
  2582                              <1> 	;
  2583                              <1> 	; ((AX = R1)) input/output
  2584                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2585                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2586                              <1> 
  2587 000051AC E85F100000          <1> 	call 	wslot
  2588                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2589                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2590 000051B1 89DF                <1> 	mov	edi, ebx ; r5
  2591 000051B3 89C2                <1> 	mov	edx, eax
  2592 000051B5 B980000000          <1> 	mov	ecx, 128
  2593                              <1> 		; mov $256.,r3
  2594 000051BA 31C0                <1> 	xor	eax, eax
  2595 000051BC F3AB                <1> 	rep	stosd
  2596 000051BE 89D0                <1> 	mov	eax, edx
  2597                              <1> ; 1: 
  2598                              <1>        		; clr (r5)+ / zero data word in buffer
  2599                              <1>        		; dec r3
  2600                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2601                              <1> 	;call	dskwr
  2602                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2603                              <1>                              ; / block specified in r1
  2604                              <1> 	; eAX (r1) = block number
  2605                              <1> 	;retn
  2606                              <1> 		; rts r0
  2607                              <1> 	; 24/12/2021
  2608 000051C0 E967100000          <1> 	jmp	dskwr
  2023                                  %include 'u4.s'      ; 15/04/2015
  2024                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2025                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2026                              <1> ; ****************************************************************************
  2027                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS4.INC
  2028                              <1> ; Last Modification: 05/12/2021
  2029                              <1> ; ----------------------------------------------------------------------------
  2030                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2031                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2032                              <1> ;
  2033                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2034                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2035                              <1> ; <Bell Laboratories (17/3/1972)>
  2036                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2037                              <1> ;
  2038                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2039                              <1> ;
  2040                              <1> ; ****************************************************************************
  2041                              <1> 
  2042                              <1> ;setisp:
  2043                              <1>        ;mov     r1,-(sp)
  2044                              <1>        ;mov     r2,-(sp)
  2045                              <1>        ;mov     r3,-(sp)
  2046                              <1>        ;mov     clockp,-(sp)
  2047                              <1>        ;mov     $s.syst+2,clockp
  2048                              <1>        ;jmp     (r0)
  2049                              <1> 
  2050                              <1> clock: ; / interrupt from 60 cycle clock
  2051                              <1> 	
  2052                              <1> 	; 14/10/2015
  2053                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2054                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2055                              <1> 
  2056                              <1>        ;mov     r0,-(sp) / save r0
  2057                              <1>        ;tst     *$lks / restart clock?
  2058                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2059                              <1>        ;inc     (r0)
  2060                              <1>        ;bne     1f
  2061                              <1>        ;inc     -(r0)
  2062                              <1> ;1:
  2063                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2064                              <1>        ;inc     (r0)
  2065                              <1>        ;bne     1f
  2066                              <1>        ;inc     -(r0)
  2067                              <1> ;1:
  2068                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2069                              <1> 
  2070 000051C5 803D[80710000]00    <1> 	cmp	byte [u.quant], 0
  2071 000051CC 772C                <1> 	ja	short clk_1
  2072                              <1> 	;
  2073 000051CE 803D[29710000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2074 000051D5 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2075 000051D7 803D[89710000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2076 000051DE 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2077 000051E0 66833D[84710000]00  <1> 	cmp	word [u.intr], 0
  2078 000051E8 7616                <1> 	jna	short clk_2
  2079                              <1> clk_0:
  2080                              <1> 	; 14/10/2015
  2081 000051EA FE05[29710000]      <1> 	inc	byte [sysflg] ; Now, we are in system space
  2082 000051F0 58                  <1> 	pop	eax ; return address to the timer interrupt
  2083                              <1> 	;
  2084 000051F1 B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2085                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2086 000051F3 E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2087                              <1> 	;
  2088 000051F5 E952EBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2089                              <1> clk_1:
  2090 000051FA FE0D[80710000]      <1> 	dec	byte [u.quant]
  2091                              <1> clk_2:
  2092 00005200 C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2093                              <1> 
  2094                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2095                              <1> 
  2096                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2097                              <1>        ;decb    (r0)
  2098                              <1>        ;bge     1f / if less than 0
  2099                              <1>        ;clrb    (r0) / make it 0
  2100                              <1> ;1: / decrement time out counts return now if priority was not 0
  2101                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2102                              <1>        ;bge     2f / yes, check time outs
  2103                              <1>        ;tstb    (r0) / no, user timed out?
  2104                              <1>        ;bne     1f / no
  2105                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2106                              <1>        ;bne     1f / no, 1f
  2107                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2108                              <1>        ;sys     0 / sysrele
  2109                              <1>        ;rti
  2110                              <1> ;2: / priority is high so just decrement time out counts
  2111                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2112                              <1> ;2:
  2113                              <1>        ;tstb    (r0) / is the time out?
  2114                              <1>        ;beq     3f / yes, 3f (get next entry)
  2115                              <1>        ;decb    (r0) / no, decrement the time
  2116                              <1>        ;bne     3f / isit zero now?
  2117                              <1>        ;incb    (r0) / yes, increment the time
  2118                              <1> ;3:
  2119                              <1>        ;inc     r0 / next entry
  2120                              <1>        ;cmp     r0,$touts / end of toutt table?
  2121                              <1>        ;blo     2b / no, check this entry
  2122                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2123                              <1>        ;rti / return from interrupt
  2124                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2125                              <1>        ;mov     (sp)+,r0 / restore r0
  2126                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2127                              <1>        ;jsr     r0,setisp / save registers
  2128                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2129                              <1>                                ;  / the table
  2130                              <1> ;1:
  2131                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2132                              <1>        ;beq     2f / yes
  2133                              <1>        ;decb    toutt(r0) / no, decrement the time
  2134                              <1>        ;bne     2f / is the time 0, now
  2135                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2136                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2137                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2138                              <1> ;2:
  2139                              <1>        ;dec     r0 / set up r0 for next entry
  2140                              <1>        ;bge     1b / finished? , no, go back
  2141                              <1>        ;br      retisp / yes, restore registers and do a rti
  2142                              <1> 
  2143                              <1> ;retisp:
  2144                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2145                              <1>        ;mov     (sp)+,r3
  2146                              <1>        ;mov     (sp)+,r2
  2147                              <1>        ;mov     (sp)+,r1
  2148                              <1>        ;mov     (sp)+,r0
  2149                              <1>        ;rti     / return from interrupt
  2150                              <1> 
  2151                              <1> 
  2152                              <1> wakeup: ; / wakeup processes waiting for an event 
  2153                              <1> 	; / by linking them to the queue
  2154                              <1> 	;
  2155                              <1> 	; 15/09/2015
  2156                              <1> 	; 29/06/2015
  2157                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2158                              <1> 	;
  2159                              <1> 	; 15/05/2013 - 02/06/2014
  2160                              <1> 	; Retro UNIX 8086 v1 modification !
  2161                              <1> 	; (Process/task switching routine by using
  2162                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2163                              <1> 	;
  2164                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2165                              <1> 	; sleeping in the specified wait channel by creating a link 
  2166                              <1> 	; to it from the last user process on the run queue.
  2167                              <1> 	; If there is no process to wake up, nothing happens.
  2168                              <1> 	;
  2169                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2170                              <1> 	; 'switching' status of the current process (owns current tty)
  2171                              <1> 	; (via alt + function keys) to a process which has highest
  2172                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2173                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2174                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2175                              <1> 	; tty for tty switching by keyboard.)	 
  2176                              <1> 	; 
  2177                              <1> 	; INPUT -> 
  2178                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2179                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2180                              <1> 	;
  2181                              <1> 	; ((modified registers: EAX, EBX))
  2182                              <1> 	;
  2183 00005201 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2184 00005204 81C3[98700000]      <1> 	add	ebx, wlist
  2185 0000520A 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2186 0000520C 20C0                <1> 	and	al, al
  2187 0000520E 7424                <1> 	jz	short wa0 ; nothing to wakeup
  2188                              <1> 	;
  2189 00005210 30E4                <1> 	xor	ah, ah
  2190 00005212 8825[80710000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2191 00005218 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2192                              <1> 	; 15/09/2015
  2193 0000521A 0FB6D8              <1> 	movzx	ebx, al
  2194 0000521D 88A3[7F6E0000]      <1> 	mov	[ebx+p.waitc-1], ah ; 0
  2195 00005223 FEC4                <1> 	inc	ah
  2196 00005225 88A3[9F6E0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2197                              <1> 	;
  2198 0000522B 57                  <1> 	push	edi
  2199 0000522C 52                  <1> 	push	edx
  2200 0000522D E84BFFFFFF          <1> 	call	putlu
  2201 00005232 5A                  <1> 	pop	edx
  2202 00005233 5F                  <1> 	pop	edi
  2203                              <1> wa0:
  2204 00005234 C3                  <1> 	retn
  2205                              <1> 
  2206                              <1> 	; 05/12/2021
  2207                              <1> 	; 30/11/2021 - Retro UNIX 386 v1.2
  2208                              <1> sleep: 
  2209                              <1> 	; 15/09/2015
  2210                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2211                              <1> 	;
  2212                              <1> 	; 09/05/2013 - 20/03/2014
  2213                              <1> 	;
  2214                              <1> 	; Retro UNIX 8086 v1 modification !
  2215                              <1> 	; (Process/task switching and quit routine by using
  2216                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2217                              <1> 	;
  2218                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2219                              <1> 	; tty and tape output or input becomes available
  2220                              <1> 	; and process is put on waiting channel and swapped out,
  2221                              <1> 	; then -when the tty or tape is ready to write or read-
  2222                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2223                              <1> 	;
  2224                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2225                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2226                              <1> 	; status of the current process also INT 1Ch will count down
  2227                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2228                              <1> 	; to tty buffer of the current process and kernel will get
  2229                              <1> 	; user input by using tty buffer of the current process
  2230                              <1> 	; (instead of standard INT 16h interrupt).
  2231                              <1> 	; TTY output will be redirected to related video page of text mode
  2232                              <1> 	; (INT 10h will be called with different video page depending
  2233                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2234                              <1> 	; pseudo screens.)
  2235                              <1> 	;
  2236                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2237                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2238                              <1> 	; characters/data on serial port(s).
  2239                              <1> 	;
  2240                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2241                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2242                              <1> 	; 
  2243                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2244                              <1> 	;
  2245                              <1> 	;; 05/10/2013
  2246                              <1>         ;10/12/2013
  2247                              <1> 	;cmp   byte [u.uno], 1
  2248                              <1>         ;ja    short sleep0
  2249                              <1> 	;retn
  2250                              <1> 
  2251                              <1> 	; 20/03/2014
  2252                              <1> 	;mov	bx, [runq]
  2253                              <1> 	;cmp	bl, bh
  2254                              <1> 	;jne	short sleep0	
  2255                              <1> 	; 25/02/2014
  2256                              <1> 	;cmp	word ptr [runq], 0
  2257                              <1> 	;ja	short sleep0	
  2258                              <1> 	;retn
  2259                              <1> sleep0:
  2260                              <1> 	;
  2261 00005235 E851000000          <1> 	call	isintr
  2262                              <1> 	;jnz	sysret
  2263                              <1> 		; / wait for event
  2264                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2265                              <1> 			      ; / or quit from user
  2266                              <1>                		; br 2f / something happened
  2267                              <1> 			      ; / yes, his interrupt so return
  2268                              <1>                      	      ;	/ to user
  2269                              <1> 	; 05/12/2021
  2270 0000523A 7405                <1> 	jz	short sleep_2
  2271                              <1> sleep_3:
  2272 0000523C E9A6EAFFFF          <1> 	jmp	sysret
  2273                              <1> sleep_2:
  2274                              <1> 	; 30/06/2015
  2275 00005241 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2276 00005244 81C3[98700000]      <1> 	add	ebx, wlist
  2277 0000524A 8A03                <1> 	mov	al, [ebx]
  2278 0000524C 20C0                <1> 	and	al, al
  2279 0000524E 7407                <1> 	jz	short sleep1
  2280 00005250 53                  <1> 	push	ebx
  2281 00005251 E827FFFFFF          <1> 	call	putlu
  2282 00005256 5B                  <1> 	pop	ebx
  2283                              <1> sleep1:
  2284 00005257 A0[89710000]        <1> 	mov	al, [u.uno]    
  2285 0000525C 8803                <1>   	mov	[ebx], al 	; put the process number
  2286                              <1> 				; in the wait channel
  2287                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2288                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2289                              <1> 				     ; / on the stack
  2290                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2291                              <1> 				     ; / to put to sleep in there
  2292                              <1> 	; 30/11/2021
  2293 0000525E 31DB                <1> 	xor	ebx, ebx
  2294 00005260 8A1D[15710000]      <1> 	mov	bl, [cdev]
  2295 00005266 53                  <1> 	push	ebx
  2296                              <1>         ; 15/09/2015
  2297                              <1> 	;movzx	ebx, al
  2298 00005267 88C3                <1> 	mov	bl, al
  2299 00005269 C683[9F6E0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2300 00005270 FEC4                <1> 	inc	ah
  2301 00005272 88A3[7F6E0000]      <1> 	mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2302                              <1> 	;
  2303                              <1> 	;push	word [cdev]
  2304                              <1> 	;	; mov cdev,-(sp) / nothing happened in isintr so
  2305 00005278 E833FEFFFF          <1> 	call	swap
  2306                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2307                              <1>         ;pop	word [cdev]
  2308                              <1> 	;	; mov (sp)+,cdev / restore device
  2309                              <1> 	; 30/11/2021
  2310 0000527D 58                  <1> 	pop	eax
  2311 0000527E A2[15710000]        <1> 	mov	[cdev], al
  2312 00005283 E803000000          <1> 	call	isintr
  2313                              <1> 	; 22/09/2013
  2314                              <1> 	;jnz	sysret         
  2315                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2316                              <1>                		; br 2f / yes, return to new user
  2317                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2318                              <1> 				; / originally on the wait channel
  2319                              <1>        		; beq 1f / if 0 branch
  2320                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2321                              <1>        		; mov $300,*$ps / processor priority = 6
  2322                              <1> 		; jsr r0,putlu / create link to old process number
  2323                              <1>        		; clr *$ps / clear the status; process priority = 0
  2324                              <1> 	; 05/12/2021
  2325 00005288 75B2                <1> 	jnz	short sleep_3 ; jump to sysret
  2326                              <1>      ;1:
  2327 0000528A C3                  <1> 	retn
  2328                              <1> 		; rts r0 / return
  2329                              <1>      ;2:
  2330                              <1>         ;;jmp	sysret
  2331                              <1> 		; jmp sysret / return to user
  2332                              <1> 
  2333                              <1> isintr:
  2334                              <1> 	; 30/11/2021	
  2335                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2336                              <1> 	;
  2337                              <1> 	; 09/05/2013 - 30/05/2014
  2338                              <1> 	;
  2339                              <1> 	; Retro UNIX 8086 v1 modification !
  2340                              <1> 	; (Process/task switching and quit routine by using
  2341                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2342                              <1> 	;
  2343                              <1> 	; Retro UNIX 8086 v1 modification:
  2344                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2345                              <1> 	;  and there is a 'quit' request by user;
  2346                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2347                              <1> 	;  "nothing to do". (20/10/2013)
  2348                              <1> 	;
  2349                              <1> 	; 20/10/2013
  2350 0000528B 66833D[6E710000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2351 00005293 761F                <1> 	jna	short isintr2 ; retn
  2352                              <1> 	; 03/09/2013
  2353                              <1> 	; (nothing to do)
  2354                              <1> 	;retn
  2355                              <1> 	; 22/09/2013
  2356 00005295 66833D[84710000]00  <1> 	cmp	word [u.intr], 0
  2357 0000529D 7615                <1> 	jna	short isintr2 ; retn
  2358                              <1> 	; 30/05/2014
  2359                              <1> 	;push	ax
  2360 0000529F 50                  <1> 	push	eax ; 30/11/2021 
  2361 000052A0 66A1[86710000]      <1> 	mov	ax, [u.quit]
  2362 000052A6 6609C0              <1> 	or	ax, ax ; 0 ?
  2363 000052A9 7408                <1> 	jz	short isintr1 ; zf = 1
  2364 000052AB 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2365 000052AF 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2366                              <1> 	;xor	ax, ax ; zf = 1
  2367                              <1> 	; 30/11/2021
  2368 000052B1 31C0                <1> 	xor	eax, eax
  2369                              <1> isintr1:
  2370                              <1> 	;pop	ax
  2371                              <1> 	; 30/11/2021
  2372 000052B3 58                  <1> 	pop	eax
  2373                              <1> isintr2: ; 22/09/2013
  2374                              <1> 	; zf=1 -> nothing to do
  2375 000052B4 C3                  <1> 	retn
  2376                              <1> 
  2377                              <1> 	; UNIX v1 original 'isintr' routine... 
  2378                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2379                              <1>        	;mov     r2,-(sp) / save r2
  2380                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2381                              <1>         ;                 / typewriter
  2382                              <1>        	;beq     1f / if 0, do nothing except skip return
  2383                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2384                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2385                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2386                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2387                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2388                              <1>         ;              / of interrupts
  2389                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2390                              <1>      ;1:
  2391                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2392                              <1>      ;4:
  2393                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2394                              <1>        	;mov     (sp)+,r1
  2395                              <1>        	;rts     r0
  2396                              <1>      ;3: / interrupt char = quit (fs)
  2397                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2398                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2399                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2400                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2401                              <1>      ;1: / find process control tty entry in tty block
  2402                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2403                              <1>        	;beq     1f / block found go to 1f
  2404                              <1>        	;add     $8,r1 / look at next tty block
  2405                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2406                              <1>        	;blo     1b / no
  2407                              <1>        	;br      4b / no process control tty found so go to 4b
  2408                              <1>      ;1:
  2409                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2410                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2411                              <1>         ;                  / identifier
  2412                              <1>        	;inc     0f / increment
  2413                              <1>      ;1:
  2414                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2415                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2416                              <1>         ;             / being typed out after you hit the interrupt
  2417                              <1>         ;             / key
  2418                              <1>        	;br      1b
  2024                                  %include 'u5.s'      ; 03/06/2015
  2025                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2026                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2027                              <1> ; ****************************************************************************
  2028                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS5.INC
  2029                              <1> ; Last Modification: 25/12/2021
  2030                              <1> ; ----------------------------------------------------------------------------
  2031                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2032                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2033                              <1> ;
  2034                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2035                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2036                              <1> ; <Bell Laboratories (17/3/1972)>
  2037                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2038                              <1> ;
  2039                              <1> ; Retro UNIX 8086 v1 - U5.AS M (07/08/2013) //// UNIX v1 -> u5.s
  2040                              <1> ;
  2041                              <1> ; ****************************************************************************
  2042                              <1> 
  2043                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2044                              <1> mget_w:
  2045                              <1> 	; 28/10/2021
  2046                              <1> 	; 22/08/2021
  2047                              <1> 	; 20/08/2021
  2048                              <1> 	; 25/05/2020
  2049                              <1> 	; 24/05/2020 - Retro UNIX 386 v2	
  2050 000052B5 C605[0A720000]01    <1> 	mov	byte [mget_rw], 1 ; write access
  2051 000052BC EB07                <1> 	jmp	short mget
  2052                              <1> mget_r:
  2053                              <1> 	; 28/10/2021
  2054                              <1> 	; 22/08/2021
  2055                              <1> 	; 25/05/2020
  2056                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2057 000052BE C605[0A720000]00    <1> 	mov	byte [mget_rw], 0 ; read access	
  2058                              <1> mget:
  2059                              <1> 	; 28/11/2021
  2060                              <1> 	; 22/11/2021
  2061                              <1> 	; 28/10/2021 - temporary (simplified code)
  2062                              <1> 	; 22/08/2021
  2063                              <1> 	; 20/08/2021
  2064                              <1> 	; 25/05/2020
  2065                              <1> 	; 24/05/2020
  2066                              <1> 	; 05/05/2020
  2067                              <1> 	; 02/05/2020, 03/05/2020
  2068                              <1> 	; 29/04/2020 - Retro UNIX 386 v2
  2069                              <1> 	; New inode model/format (Modified UNIX v7 inode model)
  2070                              <1> 	;	
  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> 	;
  2087                              <1> 	; Modified registers: eax, edx, ebx, ecx, esi, edi, ebp
  2088                              <1> 
  2089                              <1> 	; Retro UNIX 386 v2 'mget' procedure
  2090                              <1> 	; source code reference:
  2091                              <1> 	; 'mget' procedure in UNIXHDCP.ASM (25/01/2020) by Erdogan Tan
  2092                              <1> 
  2093                              <1> 	; Get sector/block address for current file pointer
  2094                              <1> 	; (If file pointer points to a number greater than current file
  2095                              <1> 	; size, a new -empty- sector/block will be created/written.)
  2096                              <1> 
  2097                              <1> 	; Note: 'mget' procedure will be used for only RUNIX v2 FS.
  2098                              <1> 	;	(installable file system drivers will not use 'mget')
  2099                              <1> 	;	 !!! 512 bytes per sector !!!  ; 02/05/2020
  2100                              <1> 
  2101                              <1> 	; ! 64 bit fofp ! but Retro UNIX 386 v2 kernel will use 32 bit
  2102                              <1> 	; file offset for regular files and directories.
  2103                              <1> 	; ('mget' procedure will be called for regular files & directories)
  2104                              <1> 
  2105                              <1> 	; 28/10/2021
  2106                              <1> 	; Note: 'mget' uses only current inode ([ii], 'inode:')
  2107                              <1> 	; (inode must be loaded at 'inode:' addr by 'iget' before 'mget')  
  2108                              <1> 
  2109                              <1> 		; mov *u.fofp,mq / file offset in mq
  2110                              <1> 		; clr ac / later to be high sig
  2111                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2112                              <1> 		; mov mq,r2
  2113                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2114                              <1> 		; bne 4f / branch for large file
  2115                              <1> mget_0:	
  2116 000052C5 8B35[48710000]      <1>         mov     esi, [u.fofp]
  2117 000052CB 8B1E                <1> 	mov	ebx, [esi]
  2118                              <1>         ; ebx = file offset
  2119                              <1> 
  2120                              <1> 	; 20/08/2021
  2121 000052CD C1EB09              <1> 	shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2122                              <1> 
  2123 000052D0 F605[D16D0000]10    <1> 	test	byte [i.flgs+1], 10h ; is this a large or small file addr?
  2124                              <1> 	;jz	short mget_1 ; small file addressing
  2125                              <1> 	;jmp	mget_5	; large file addressing
  2126 000052D7 7566                <1> 	jnz	short mget_5 ; 03/05/2020
  2127                              <1> mget_1:
  2128                              <1> 	; If large file flag is clear -not set- RUNIX v2 FS inode
  2129                              <1> 	; will contain 10 direct disk block/sector dword pointers.
  2130                              <1> 
  2131                              <1> 	; 05/05/2020
  2132                              <1> 	;shr	ebx, 9 ; / 512 (to convert byte offset to sector offset)
  2133                              <1> 
  2134 000052D9 83FB0A              <1> 	cmp	ebx, 10	; block 10
  2135 000052DC 7324                <1> 	jnb	short mget_3 ; file offset >= 5120
  2136                              <1> 
  2137                              <1> 	; 05/05/2020
  2138                              <1> 	;cmp	ebx, 5120
  2139                              <1> 	;jnb	short mget_3 ; file offset >= 5120
  2140                              <1> 
  2141                              <1> 	;mov	bl, bh
  2142                              <1> 	;and	bl, 1Eh ; clear all bits but bits 1,2,3,4 ; 0,2,..,18
  2143                              <1> 	;	; max. value = 12h = 10010b = 18 (because ebx <= 5119) 
  2144                              <1> 	;shl	bl, 1	; * 2 ; max. value = 24h = 100100b = 36
  2145                              <1> 	;xor	bh, bh  ; clear bh
  2146                              <1> 		; RUNIX v2 (RUFS 2) file system bytes per sector value
  2147                              <1> 		; is always 512.
  2148                              <1> 		; ebx = 4*(ebx/512)  = 0 to 36
  2149                              <1> 
  2150                              <1> 	; 05/05/2020
  2151 000052DE C0E302              <1> 	shl	bl, 2 ; * 4
  2152                              <1> 		 ; ebx = 0 to 36
  2153                              <1> 
  2154 000052E1 8B83[DC6D0000]      <1> 	mov	eax, [ebx+i.dskp] ; disk sector addr ptr 0 to 9 for file
  2155                              <1> 	; 22/08/2021
  2156 000052E7 89DE                <1> 	mov	esi, ebx
  2157 000052E9 31DB                <1> 	xor	ebx, ebx ; 0
  2158                              <1> 
  2159 000052EB 09C0                <1> 	or	eax, eax
  2160 000052ED 7512                <1> 	jnz	short mget_2 ; existing block/sector
  2161                              <1> 
  2162 000052EF 56                  <1> 	push	esi ; * ; 22/08/2021
  2163 000052F0 E846010000          <1> 	call	alloc_m ; 24/05/2020	
  2164                              <1> 	;call	alloc	; allocate a new sector/block for this file	
  2165                              <1> 			; eax = sector/block number
  2166                              <1> 			; ebx = buffer header address
  2167 000052F5 5E                  <1> 	pop	esi ; * ; 22/08/2021
  2168                              <1> 	; 28/11/2021
  2169                              <1> 	;jc	short mget_2 
  2170                              <1> 			; cf = 1 -> eax = 'no free block' error
  2171                              <1> 	; 22/08/2021
  2172 000052F6 8986[DC6D0000]      <1> 	mov	[esi+i.dskp], eax  ; logical sector/block address
  2173                              <1> 
  2174                              <1> 	;call	setimod	; set inode modification flag
  2175                              <1> 			; and set modification time
  2176                              <1> 	; 24/05/2020
  2177                              <1> 	;retn
  2178 000052FC E982040000          <1> 	jmp	setimod
  2179                              <1> 
  2180                              <1> 	; eax = logical sector/block number
  2181                              <1> 	; ([idev] = logical drive number)
  2182                              <1> 	; 28/10/2021
  2183                              <1> 	; [cdev] = logical drive number (0 or 1)
  2184                              <1> 	;	(0 = root fs, 1 = mounted fs)
  2185                              <1> mget_2:
  2186 00005301 C3                  <1> 	retn
  2187                              <1> 		; rts r0
  2188                              <1> mget_3: ; 3: / adding on block which changes small file to a large file
  2189                              <1> 	; 22/11/2021
  2190 00005302 E834010000          <1> 	call	alloc_m ; 24/05/2020
  2191                              <1> 	;call	alloc	; allocate a new sector/block for this file
  2192                              <1> 			; eax = sector/block number
  2193                              <1> 			; ebx = buffer header  ; 24/05/2020
  2194                              <1> 	; 28/11/2021
  2195                              <1> 	;jc	short mget_2 ; error code in eax
  2196                              <1>         ; EAX (r1) = Physical block number
  2197 00005307 E8040F0000          <1> 	call 	wslot
  2198                              <1> 		; jsr r0,wslot / set up I/O buffer for write, r5 points to 
  2199                              <1> 			     ; / first data word in buffer
  2200                              <1>         ; EAX (r1) = Physical block number
  2201                              <1> 	; 28/11/2021
  2202                              <1> 	; ebx = buffer (data) address
  2203                              <1> 	; 22/11/2021
  2204 0000530C 31C9                <1> 	xor	ecx, ecx
  2205 0000530E B10A                <1> 	mov 	cl, 10	; r3, transfer old physical block pointers
  2206                              <1> 			; into new indirect block area for the new
  2207                              <1> 			; large file		
  2208 00005310 89DF                <1> 	mov 	edi, ebx ; r5
  2209 00005312 BE[DC6D0000]        <1> 	mov	esi, i.dskp  ; current inode's direct disk addr ptrs
  2210 00005317 89C2                <1> 	mov	edx, eax
  2211 00005319 31C0                <1> 	xor	eax, eax
  2212                              <1> mget_4:
  2213 0000531B A5                  <1> 	movsd 	
  2214 0000531C 8946FC              <1> 	mov	[esi-4], eax ; 0
  2215 0000531F E2FA                <1> 	loop	mget_4
  2216                              <1> 
  2217                              <1> 	; 22/11/2021
  2218 00005321 B176                <1> 	mov 	cl, 128-10 ; clear rest of data buffer
  2219                              <1> ;mget_4: ; 1
  2220 00005323 F3AB                <1> 	rep 	stosd
  2221                              <1> 		; clr (r5)+
  2222                              <1> 		; dec r3
  2223                              <1> 		; bgt 1b
  2224 00005325 89D0                <1> 	mov	eax, edx
  2225                              <1>         ; EAX (r1) = Physical block number
  2226 00005327 E8000F0000          <1> 	call	dskwr
  2227                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2228                              <1>         ; EAX (r1) = Physical block number
  2229 0000532C A3[DC6D0000]        <1> 	mov 	[i.dskp], eax ; 22/11/2021 
  2230                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2231 00005331 800D[D16D0000]10    <1> 	or	byte [i.flgs+1], 10000b ; 10h ; 16  ; large file flag
  2232                              <1> 		; bis $10000,i.flgs / set large file bit 
  2233                              <1> 				  ; / in i.flgs word of i-node
  2234 00005338 E846040000          <1> 	call	setimod
  2235                              <1> 		; jsr r0,setimod / set i-node modified flag
  2236                              <1> 
  2237 0000533D EB86                <1> 	jmp	short mget_0 
  2238                              <1> 		; br mget
  2239                              <1> 
  2240                              <1> mget_5:  ; 4 ; large file
  2241                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2242                              <1> 	;
  2243                              <1> 	; Retro UNIX 386 v2 disk inode contains..
  2244                              <1> 	; (if large file flag is set)
  2245                              <1> 	; 8 indirect disk block/sector dword pointers
  2246                              <1> 	; +1 double indirect disk block/sector dword pointers
  2247                              <1> 	; +1 triple indirect disk block/sector dword pointers
  2248                              <1> 
  2249                              <1> 	; check indirect pointers limit (as file offset)
  2250                              <1> 	; 8*128 = 1024 blocks (or sectors) or 512 KB
  2251                              <1> 	; check dx (file offset hw) value
  2252                              <1> 	
  2253                              <1> 	; 03/05/2020
  2254                              <1> 	;cmp	ebx, 524288  ; is file offset >= 524288 ?
  2255                              <1> 	;jnb	short mget_6 ; yes, check double indirect limit
  2256                              <1> 
  2257                              <1> 	; 05/05/2020
  2258 0000533F 81FB00040000        <1> 	cmp	ebx, 1024    ; block 1024 (byte 524288)	
  2259 00005345 7321                <1> 	jnb	short mget_6 ; check double indirect limit
  2260                              <1> 
  2261 00005347 C605[0C720000]01    <1> 	mov	byte [level], 1 ; levels, 1 = indirect blocks
  2262                              <1> 
  2263                              <1> 	; 05/05/2020
  2264                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2265                              <1> 
  2266 0000534E 88D9                <1> 	mov	cl, bl
  2267 00005350 80E17F              <1> 	and	cl, 127
  2268 00005353 880D[0D720000]      <1> 	mov	[level+1], cl ; level 1, direct block ptr index (0 to 127)
  2269 00005359 66C1EB07            <1> 	shr	bx, 7 ; bl = level 0, indirect block pointer index (0 to 7)
  2270                              <1> 	;mov	[level+2], bl
  2271                              <1> 
  2272 0000535D C0E302              <1> 	shl	bl, 2 ; * 4 to convert index number to offset
  2273                              <1> 
  2274                              <1> 	;mov	esi, i.dskp
  2275                              <1> 	;add	esi, ebx
  2276                              <1> 
  2277 00005360 8DB3[DC6D0000]      <1> 	lea	esi, [ebx+i.dskp]
  2278                              <1> 
  2279 00005366 EB66                <1> 	jmp	short mget_8
  2280                              <1> 
  2281                              <1> mget_6:
  2282                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2283                              <1> 	; 03/05/2020
  2284                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2285                              <1> 	; check double indirect pointer limit (as file offset)
  2286                              <1> 	; (128*128)+1024 = 16384+1024 blocks or 8 MB + 512 KB
  2287                              <1> 	; check dx (file offset hw) value
  2288                              <1> 	
  2289                              <1> 	;cmp	ebx, 8912896 ; >= 17408 sectors (16384+1024) ?	
  2290                              <1> 	;jnb	short mget_7 ; yes, use triple indirect pointer (block)
  2291                              <1> 
  2292                              <1> 	; 05/05/2020
  2293 00005368 81FB00440000        <1> 	cmp	ebx, 17408   ; block 17408 (byte 8912896)	
  2294 0000536E 7329                <1> 	jnb	short mget_7 ; use triple indirect pointer (block)
  2295                              <1> 
  2296 00005370 C605[0C720000]02    <1> 	mov	byte [level], 2  ; levels, 2 = double indirect blocks
  2297                              <1> 	
  2298                              <1> 	;sub	ebx, 524288 ; 1024 sectors
  2299                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2300                              <1> 			; (from sector 1024)
  2301                              <1> 	; 05/05/2020
  2302 00005377 81EB00040000        <1> 	sub	ebx, 1024 ; offset from sector 1024
  2303                              <1> 	
  2304 0000537D 88D9                <1> 	mov	cl, bl
  2305 0000537F 80E17F              <1> 	and	cl, 127
  2306 00005382 880D[0D720000]      <1> 	mov	[level+1], cl
  2307                              <1> 			; level 2, direct block ptr index (0 to 127)	
  2308 00005388 66C1EB07            <1> 	shr	bx, 7
  2309 0000538C 881D[0E720000]      <1> 	mov	[level+2], bl
  2310                              <1> 			; level 1, indirect block ptr index (0 to 127)
  2311                              <1> 
  2312 00005392 BE[FC6D0000]        <1> 	mov	esi, i.dskp + 32 ; 8*4
  2313                              <1> 			; level 0, double indirect block pointer
  2314 00005397 EB35                <1> 	jmp	short mget_8
  2315                              <1> 
  2316                              <1> mget_7:
  2317                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2318                              <1> 	; 03/05/2020
  2319                              <1> 	; 13/11/2019 (UNIXHDCP.ASM)
  2320                              <1> 	; triple indirect pointer ; 8912896 to 1082654720 bytes
  2321                              <1> 	;mov	esi, i.dskp + 36 ; 9*4
  2322                              <1> 
  2323 00005399 C605[0C720000]03    <1> 	mov	byte [level], 3  ; levels, 3 = triple indirect blocks
  2324                              <1> 
  2325                              <1> 	;sub	ebx, 8912896 ; 17408 sectors (16384+1024)
  2326                              <1> 	;shr	ebx, 9	; ebx = sector offset (flat)
  2327                              <1> 			; (from sector 17408)
  2328                              <1> 	; 05/05/2020
  2329 000053A0 81EB00440000        <1> 	sub	ebx, 17408 ; offset from sector 17408	
  2330                              <1> 
  2331 000053A6 88D9                <1> 	mov	cl, bl
  2332 000053A8 80E17F              <1> 	and	cl, 127
  2333 000053AB 880D[0D720000]      <1> 	mov	[level+1], cl  
  2334                              <1> 			; level 3, direct block ptr index (0 to 127)	
  2335 000053B1 C1EB07              <1> 	shr	ebx, 7	
  2336 000053B4 88D9                <1> 	mov	cl, bl
  2337 000053B6 80E17F              <1> 	and	cl, 127
  2338 000053B9 880D[0E720000]      <1> 	mov	[level+2], cl
  2339                              <1> 			; level 2, indirect block ptr index (0 to 127)
  2340 000053BF 66C1EB07            <1> 	shr	bx, 7
  2341 000053C3 881D[0F720000]      <1> 	mov	[level+3], bl
  2342                              <1> 			; level 1, double indir blk ptr index (0 to 127)
  2343                              <1> 
  2344 000053C9 BE[006E0000]        <1> 	mov	esi, i.dskp + 36 ; 9*4
  2345                              <1> 			; level 0, triple indirect block pointer
  2346                              <1> mget_8:
  2347                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibiliy modification
  2348 000053CE 8B06                <1> 	mov	eax, [esi]
  2349 000053D0 09C0                <1> 	or 	eax, eax ; R1
  2350 000053D2 7515                <1> 	jnz 	short mget_10 ; 2f
  2351                              <1> 		; bne 2f / if no indirect block exists
  2352 000053D4 56                  <1> 	push	esi	; * ; 24/05/2020
  2353                              <1> 
  2354 000053D5 E861000000          <1> 	call	alloc_m ; 24/05/2020
  2355                              <1> 	;call	alloc	; allocate a new block for this file	
  2356                              <1> 			; eax = block number
  2357                              <1> 			; ebx = buffer header address
  2358                              <1> 			; [pdn] = physical drive number ; 25/05/2020
  2359                              <1> 	;jc	mget_2	; cf -> 1 & eax = 0 -> no free block
  2360                              <1> 
  2361 000053DA 5E                  <1> 	pop	esi	; * ; 24/05/2020
  2362                              <1> 	;jc	short mget_9
  2363                              <1> 
  2364 000053DB 8906                <1> 	mov	[esi], eax ; record sector/block address on i.dskp area
  2365                              <1> 
  2366 000053DD E8A1030000          <1> 	call 	setimod
  2367                              <1> 		; jsr r0,setimod / set i-node modified byte
  2368                              <1> 	; EAX = new block number
  2369 000053E2 E8C5FDFFFF          <1> 	call 	clear
  2370                              <1> 		; jsr r0,clear / clear new block
  2371                              <1> 	; 22/11/2021
  2372 000053E7 EB05                <1> 	jmp	short mget_11
  2373                              <1> ;mget_9:
  2374                              <1> ;	retn
  2375                              <1> mget_10: ;2
  2376                              <1> 	; 05/03/2013
  2377                              <1> 	; EAX = r1, physical block number (of indirect block)
  2378 000053E9 E8C20D0000          <1> 	call 	dskrd ; read indirect block
  2379                              <1> 		; jsr r0,dskrd / read in indirect block
  2380                              <1> 	;jc	short mget_9
  2381                              <1> mget_11:
  2382                              <1> 	; 22/11/2021
  2383                              <1> 	; eax = physical block/sector address
  2384                              <1> 	; ebx = buffer address
  2385                              <1> 
  2386 000053EE 89C2                <1> 	mov	edx, eax ; *  ; save sector number in edx
  2387                              <1> 
  2388 000053F0 0FB605[0C720000]    <1> 	movzx	eax, byte [level]
  2389 000053F7 8A80[0C720000]      <1> 	mov	al, [eax+level] ; get sector pointer offset
  2390 000053FD 66C1E002            <1> 	shl	ax, 2 ; * 4
  2391                              <1> 
  2392 00005401 01C3                <1> 	add	ebx, eax
  2393                              <1> 
  2394 00005403 8B03                <1> 	mov 	eax, [ebx] ; put physical block no of block
  2395                              <1> 			   ; in file sought in R1 (EAX)
  2396                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2397                              <1> 	               	    ; / sought in r1
  2398                              <1> 
  2399 00005405 21C0                <1> 	and	eax, eax  ; if logical sector/block number is zero
  2400                              <1> 			  ; then we need a new block for file
  2401 00005407 740B                <1> 	jz	short mget_12
  2402                              <1> 
  2403 00005409 FE0D[0C720000]      <1> 	dec	byte [level]
  2404 0000540F 75D8                <1> 	jnz	short mget_10
  2405                              <1> 
  2406 00005411 29DB                <1> 	sub	ebx, ebx ; ebx = 0 ; existing sector
  2407                              <1> 
  2408 00005413 C3                  <1> 	retn
  2409                              <1> 
  2410                              <1> mget_12:
  2411                              <1> 	; 22/11/2021
  2412 00005414 52                  <1> 	push	edx ; *
  2413 00005415 53                  <1> 	push	ebx ; **	 ; buffer data position
  2414 00005416 E820000000          <1> 	call	alloc_m
  2415                              <1> 	;call	alloc	 ; allocate a new block for this file	
  2416                              <1> 			 ; eax = block number (logical)
  2417                              <1> 			 ; ebx = buffer header address
  2418 0000541B 5E                  <1> 	pop	esi ; **
  2419 0000541C 5A                  <1> 	pop	edx ; *
  2420                              <1> 	;jc	short mget_9 ; cf -> 1 & eax = 0 -> no free block
  2421                              <1> 
  2422 0000541D 8906                <1> 	mov	[esi], eax ; record/save block number (logical)
  2423                              <1> 
  2424                              <1> 	; 22/11/2021
  2425 0000541F 870424              <1> 	xchg	eax, [esp] ; *
  2426                              <1> 
  2427                              <1> 	; eax (r1) = physical block number (of indirect block)
  2428 00005422 E8E90D0000          <1> 	call 	wslot
  2429                              <1> 		; jsr r0,wslot
  2430                              <1>         ; eax (r1) = physical block number
  2431                              <1> 	; ebx (r5) = pointer to buffer (indirect block)
  2432 00005427 E8000E0000          <1> 	call 	dskwr
  2433                              <1> 	; eax = r1 = physical block number (of indirect block)
  2434                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2435                              <1> 			     ; / back out on disk
  2436 0000542C 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2437                              <1> 		; mov (sp),r1 / restore block number of new block	
  2438                              <1> 	; eax (r1) = physical block number of new block
  2439 0000542D E87AFDFFFF          <1> 	call 	clear
  2440                              <1> 		; jsr r0,clear / clear new block
  2441                              <1> 
  2442 00005432 FE0D[0C720000]      <1> 	dec	byte [level]
  2443 00005438 75B4                <1> 	jnz	short mget_11
  2444                              <1> 	
  2445                              <1> 	; 22/11/2021
  2446                              <1> 	; ebx = buffer address
  2447                              <1> mget_13: ; 2
  2448                              <1> 	; eax (r1) = Block number of new block
  2449 0000543A C3                  <1> 	retn
  2450                              <1> 		; rts r0
  2451                              <1> 
  2452                              <1> 	; 26/11/2021
  2453                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2454                              <1> alloc_m:
  2455                              <1> 	; 27/11/2021
  2456                              <1> 	; 28/10/2021
  2457                              <1> 	; 07/05/2021
  2458                              <1> 	; 26/05/2020
  2459                              <1> 	; 25/05/2020
  2460                              <1> 	; 24/05/2020 - Retro UNIX 386 v2
  2461                              <1> 	; 'alloc' call in 'mget'
  2462                              <1> 	;
  2463                              <1> 	; (('mget_r' will be returned with error))
  2464                              <1> 	; (('mget_w' will continue to 'alloc'))
  2465                              <1> 
  2466                              <1> 	; Note: 'sysread' will return with cf = 0, eax = 0
  2467                              <1> 	; if [fofp] >= file size (eax = 0 --> EOF)
  2468                              <1> 	; So, if we are here, that means [fofp] < file size
  2469                              <1> 	;     but disk address is 0. 
  2470                              <1> 	
  2471 0000543B 803D[0A720000]01    <1> 	cmp	byte [mget_rw], 1 ; write access ? (mget_w) 
  2472 00005442 730F                <1> 	jnb	short alloc ; yes (this is a call from 'mget_w')
  2473                              <1> 	; ((cf = 1))	
  2474                              <1> 	; no (this is a call from 'mget_r') !
  2475                              <1> 	;mov	eax, ERR_FILE_SIZE ; file size error (inode error!)
  2476                              <1> 		; [User may change this empty/invalid inode (disk) sector
  2477                              <1> 		; pointer with a new valid inode (disk) sector pointer 
  2478                              <1> 		; by writing new clear (zero) sector to same file position
  2479                              <1> 		; in order to correct file size -inode parm/content- error.
  2480                              <1> 		; It may be useful for recovering lost data if other sector
  2481                              <1> 		; pointers are not empty.]	
  2482                              <1> 	;retn
  2483                              <1> 	; 27/11/2021
  2484 00005444 C705[AC710000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE 
  2484 0000544C 0000                <1>
  2485                              <1> 			; file size error (inode error!)
  2486 0000544E E974E8FFFF          <1> 	jmp	error
  2487                              <1> alloc:
  2488                              <1> 	; 27/11/2021
  2489                              <1> 	; 26/11/2021 - Major modification for Runix v2 file system
  2490                              <1> 	;	(I have called this kernel version as v1.2, it is a
  2491                              <1> 	;	 debug/test version just before Retro UNIX 386 v2 kernel)
  2492                              <1> 	;	((there were running problems on new version, 
  2493                              <1> 	;	  so i am developing an intermediate version with minimum
  2494                              <1> 	;	  modification on v1.1 code which is successfuly running))
  2495                              <1> 	;	 ; /// Erdogan Tan - Istanbul, 26/11/2021 /// 
  2496                              <1> 	;	 
  2497                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2498                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2499                              <1> 	;
  2500                              <1> 	; get a free block and 
  2501                              <1> 	; set the corresponding bit in the free storage map
  2502                              <1> 	; 
  2503                              <1> 	; INPUTS ->
  2504                              <1> 	;    cdev (current device)
  2505                              <1> 	;    r2 
  2506                              <1> 	;    r3
  2507                              <1> 	; OUTPUTS ->
  2508                              <1> 	;    r1 (physical block number of block assigned)
  2509                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2510                              <1> 	;
  2511                              <1> 	; ((AX = R1)) output
  2512                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2513                              <1>         ;    ((Modified registers: edx, ecx)) 
  2514                              <1> 
  2515                              <1> 	; 26/11/2021
  2516                              <1> 	; INPUT:
  2517                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2518                              <1> 	; OUTPUT:
  2519                              <1> 	;	eax = disk block/sector number/address (physical)
  2520                              <1> 	;	(ebx = disk buffer address for sector/block in eax)
  2521                              <1> 	;
  2522                              <1> 	;    Note:	
  2523                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2524                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2525                              <1> 	;	modification flag will be set; but the superblock 
  2526                              <1> 	;	will not be written to it's disk in this 'alloc' procedure)
  2527                              <1> 	;
  2528                              <1> 	; Modified registers: eax, ebx, ecx, edx, esi, edi, ebp 
  2529                              <1> 
  2530                              <1> 	; 26/11/2021
  2531 00005453 BB[14720000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2532                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2533 00005458 F605[15710000]01    <1> 	test	byte [cdev], 1
  2534                              <1> 		; tst cdev
  2535 0000545F 7405                <1> 	jz	short alloc_1
  2536                              <1> 		; beq 1f / drum is device
  2537 00005461 BB[1C740000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2538                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2539                              <1> 			      ; / free storage map
  2540                              <1> alloc_1: ; 1
  2541                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2542                              <1> 	;test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2543                              <1> 	;jnz	short alloc_2  ; 'read only file system' error
  2544                              <1> 	;
  2545 00005466 8B4B38              <1> 	mov	ecx, [ebx+SB.FreeBlocks] ; count of free blocks/sectors
  2546 00005469 21C9                <1> 	and	ecx, ecx
  2547 0000546B 750F                <1> 	jnz	short alloc_3
  2548                              <1> alloc_2:
  2549                              <1> 	; 'no free blocks on disk !' error
  2550 0000546D C705[AC710000]2100- <1> 	mov	dword [u.error], ERR_ALLOC
  2550 00005475 0000                <1>
  2551 00005477 E94BE8FFFF          <1> 	jmp	error
  2552                              <1> alloc_3:
  2553                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2554 0000547C 31C0                <1> 	xor	eax, eax
  2555                              <1> 	; 23/07/2021
  2556 0000547E 8B4B3C              <1> 	mov	ecx, [ebx+SB.FirstFreeBlk] ; 1st free sector number
  2557                              <1> 					 ; (as logical sector number)
  2558 00005481 09C9                <1> 	or	ecx, ecx
  2559 00005483 7415                <1> 	jz	short alloc_5 ; 0 = initial/reset value or 'not valid'
  2560 00005485 41                  <1> 	inc	ecx ; 0FFFFFFFFh -> 0
  2561 00005486 7412                <1> 	jz	short alloc_5 ; 'not valid' or 'not calculated'
  2562 00005488 49                  <1> 	dec	ecx ; restore first free block value
  2563 00005489 89C8                <1> 	mov	eax, ecx
  2564                              <1> 	; 1 allocation byte (in fbm) is for 8 sectors
  2565 0000548B C1E903              <1> 	shr	ecx, 3 ; first free block number / 8
  2566 0000548E 80E1FC              <1> 	and	cl, ~3  ; dword alignment (to backward)
  2567                              <1> 	; 27/11/2021
  2568 00005491 890D[1C760000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2569                              <1> alloc_4:
  2570 00005497 C1E80C              <1> 	shr	eax, 12 ; 1 fbm sector for 4096 sectors
  2571                              <1> alloc_5:
  2572                              <1> 	; 26/11/2021
  2573 0000549A 53                  <1> 	push	ebx ; ** ; superblock buffer address 
  2574                              <1> 	; eax = fbm sector index
  2575 0000549B A3[20760000]        <1> 	mov	[free_map_index], eax
  2576 000054A0 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2577                              <1> 			; free blocks map start sector addr
  2578                              <1> 	;add	eax, [ebx+SB.BootSectAddr] 
  2579                              <1> 	;		; + Hidden Sectors
  2580                              <1> 	; eax = physical sector number
  2581 000054A3 E8080D0000          <1> 	call	dskrd
  2582                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2583                              <1> 	; eax = physical sector number
  2584                              <1> 	; ebx = buffer data address
  2585                              <1> 	; 27/11/2021
  2586 000054A8 8B15[1C760000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2587 000054AE A3[24760000]        <1> 	mov	[free_map_sector], eax ; physical sector number
  2588 000054B3 B9FF010000          <1> 	mov	ecx, 511
  2589                              <1> 	;and	edx, 511
  2590 000054B8 21CA                <1> 	and 	edx, ecx ; fbm byte offset in fbm buffer
  2591 000054BA 41                  <1> 	inc	ecx ; 512
  2592 000054BB 01D9                <1> 	add	ecx, ebx
  2593 000054BD 01DA                <1> 	add	edx, ebx ; + buffer address
  2594 000054BF 5B                  <1> 	pop	ebx ; ** ; superblock buffer address 
  2595                              <1> 	;
  2596                              <1> 	; ebx = superblock buffer address
  2597                              <1> 	; edx = superblock buffer address + byte offset (dword aligned)
  2598                              <1> 	; ecx = superblock buffer address + 512
  2599                              <1> alloc_6:
  2600                              <1> 	; 26/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2601                              <1> 	;		for Retro UNIX 386 v1.2
  2602                              <1> 	; 25/05/2020 - Retro UNIX 386 v2 code
  2603                              <1> 	; (dword scan) ((1 dword = 32 sectors, 1 byte = 8 sectors))
  2604                              <1> 	; ((Note: Logical drive size must be multiplies of 32 sectors))
  2605                              <1> 	; 19/05/2020
  2606                              <1> 	; edx = free blocks map byte address 
  2607 000054C0 0FBC02              <1> 	bsf	eax, [edx] ; Scans source operand for first bit set (1).
  2608                              <1> 			  ; Clear ZF if a bit is found set (1) and 
  2609                              <1> 			  ; loads the destination with an index to
  2610                              <1> 			  ; first set bit. (0 -> 31) 
  2611                              <1> 			  ; Sets ZF to 1 if no bits are found set.
  2612 000054C3 752A                <1> 	jnz	short alloc_8 ; ZF = 0 -> a free block has been found
  2613                              <1> 
  2614 000054C5 A1[1C760000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2615 000054CA 83C004              <1> 	add	eax, 4 ; next dword
  2616 000054CD 3B431C              <1> 	cmp	eax, [ebx+SB.FreeMapSize] ; fbm size in bytes
  2617 000054D0 7209                <1> 	jb	short alloc_7
  2618                              <1> 	; invalidate superblock's first free block field
  2619 000054D2 C7433CFFFFFFFF      <1> 	mov	dword [ebx+SB.FirstFreeBlk], 0FFFFFFFFh
  2620                              <1> 	; 'no free blocks on disk !' error
  2621 000054D9 EB92                <1> 	jmp	alloc_2
  2622                              <1> alloc_7:
  2623                              <1> 		; 26/05/2020
  2624                              <1> 		; NOTE: If ldrv size is not multiplies of 32 sectors,
  2625                              <1> 		; mod (ldrv size / 32) sectors (at the end of ldrv)
  2626                              <1> 		; can not be allocated (for regular files or dirs)! 
  2627                              <1> 		; (Kernel or runix fs installation program can use
  2628                              <1> 		;  this fact to save/duplicate critical sectors/data 
  2629                              <1> 		;  onto end sectors of that logical drive's runix fs.)
  2630                              <1> 
  2631                              <1> 	; 26/11/2021
  2632 000054DB A3[1C760000]        <1> 	mov	[free_map_offset], eax
  2633                              <1> 	; 28/07/2021
  2634                              <1> 	; set next first free block value for search
  2635 000054E0 C1E003              <1> 	shl	eax, 3 ; * 8 ; first free block
  2636                              <1>  	; 26/11/2021
  2637 000054E3 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2638                              <1> 	; search (scan) for next free block map dword (in buffer)
  2639 000054E6 83C204              <1> 	add	edx, 4 ; next dword
  2640 000054E9 39CA                <1> 	cmp	edx, ecx
  2641 000054EB 72D3                <1> 	jb	short alloc_6
  2642                              <1> 	; 27/11/2021
  2643 000054ED EBA8                <1> 	jmp	short alloc_4
  2644                              <1> 
  2645                              <1> alloc_8:
  2646                              <1> 	; 26/11/2021
  2647                              <1> 	; convert bit index to xor value
  2648                              <1> 	; and then set allocated flag for corresponding fbm bit 
  2649 000054EF 89C1                <1> 	mov	ecx, eax
  2650                              <1> 	;mov	cl, al 
  2651                              <1> 	;sub	eax, eax
  2652                              <1> 	;inc	al ; eax = 1
  2653 000054F1 B001                <1> 	mov	al, 1
  2654 000054F3 D3E0                <1> 	shl	eax, cl
  2655 000054F5 3102                <1> 	xor	[edx], eax  ; clear allocated block's bit in the fbm
  2656                              <1> 	; zero bit means allocated disk block (1 means free disk block) 
  2657                              <1> 
  2658 000054F7 A1[1C760000]        <1> 	mov	eax, [free_map_offset] ; byte offset from start of fbm
  2659                              <1> 		; note: eax is dword aligned (0,4,8,12..) !
  2660 000054FC C1E003              <1> 	shl	eax, 3 ; * 8 ; free block number base
  2661 000054FF 01C8                <1> 	add	eax, ecx ; add allocation bit index (0 to 31)	
  2662 00005501 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax ; current free block
  2663                              <1> 				; (which is being allocated here)
  2664                              <1> 
  2665                              <1> 	;mov	eax, [ebx+SB.FreeMapAddr] 
  2666                              <1> 	;		; free blocks map start sector addr
  2667                              <1> 	;add	eax, [free_map_index]
  2668                              <1> 	
  2669                              <1> 	;;add	eax, [ebx+SB.BootSectAddr] 
  2670                              <1> 	;		; + Hidden Sectors
  2671                              <1> 	; eax = physical sector number
  2672                              <1> 	
  2673                              <1> 	; 27/11/2021
  2674 00005504 A1[24760000]        <1> 	mov	eax, [free_map_sector] ; physical sector number
  2675                              <1> 	
  2676 00005509 E8020D0000          <1> 	call	wslot
  2677                              <1> 	; ebx = buffer data address (write operation bit is set)
  2678                              <1> 	; eax = physical sector number
  2679                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2680                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2681                              <1> 
  2682                              <1> 	; 27/11/2021
  2683                              <1> 	;mov	[free_map_buffer], ebx ; save free map buffer address
  2684                              <1> 
  2685 0000550E E8190D0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2686                              <1> 		      ; (at the beginning/head of the buffer chain)
  2687                              <1> 
  2688                              <1> 	; if we are here, buffer has been written to disk successfully 
  2689                              <1> 	; (otherwise cpu would jump to 'error' address)
  2690                              <1> 
  2691                              <1> 	; set superblock modified flag
  2692 00005513 BA[27710000]        <1> 	mov	edx, smod
  2693 00005518 BB[14720000]        <1> 	mov	ebx, systm
  2694 0000551D F605[15710000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2695 00005524 7406                <1> 	jz	short alloc_9  ; no, root device
  2696                              <1> 	; yes, mounted device
  2697 00005526 BB[1C740000]        <1> 	mov	ebx, mount
  2698                              <1> 	;mov	edx, mmod
  2699 0000552B 42                  <1> 	inc	edx ; edx = offset mmod
  2700                              <1> alloc_9: 
  2701 0000552C FE02                <1> 	inc	byte [edx] ; superblock modified !
  2702                              <1> 	
  2703                              <1> 	; Allocating a new sector/block (for file) has been completed here.
  2704 0000552E 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2705 00005531 40                  <1> 	inc	eax ; 0FFFFFFFFh -> 0 
  2706 00005532 7405                <1> 	jz	short alloc_10 ; not valid (not set)
  2707 00005534 48                  <1> 	dec	eax ; Free Blocks
  2708 00005535 48                  <1> 	dec	eax ; Free Blocks = Free Blocks - 1
  2709 00005536 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax
  2710                              <1> alloc_10:
  2711 00005539 E8A50D0000          <1> 	call	get_system_time
  2712                              <1> 		; eax = current time (as unix epoch time)
  2713                              <1> 	; 30/07/2021
  2714 0000553E 89435C              <1> 	mov	[ebx+SB.ModifTime], eax
  2715                              <1> 
  2716 00005541 8B433C              <1> 	mov	eax, [ebx+SB.FirstFreeBlk] ; allocated block address
  2717 00005544 FF433C              <1> 	inc	dword [ebx+SB.FirstFreeBlk] 
  2718                              <1> 				; +1, new value of first free block
  2719                              <1> 				; (new search will be started from here)
  2720                              <1> 				; ((it may not be free, no problem))
  2721                              <1> 
  2722                              <1> 	; put free map buffer address in ebx
  2723                              <1> 	; 27/11/2021
  2724                              <1> 	;mov	ebx, [free_map_buffer]
  2725                              <1> 
  2726 00005547 C3                  <1> 	retn	
  2727                              <1> 
  2728                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2729                              <1> free:
  2730                              <1> 	; 05/11/2021
  2731                              <1> 	; 29/10/2021 - temporary (simplified code)
  2732                              <1> 	; 14/08/2021
  2733                              <1> 	; 12/06/2021
  2734                              <1> 	; 07/06/2020
  2735                              <1> 	; 25/05/2020 (Retro UNIX 386 v2 - Beginning)
  2736                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2737                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2738                              <1> 	;
  2739                              <1> 	; calculates byte address and bit position for given block number
  2740                              <1> 	; then sets the corresponding bit in the free storage map
  2741                              <1> 	; 
  2742                              <1> 	; INPUTS ->
  2743                              <1> 	;    r1 - block number for a block structured device
  2744                              <1> 	;    cdev - current device 
  2745                              <1> 	; OUTPUTS ->
  2746                              <1> 	;    free storage map is updated
  2747                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2748                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2749                              <1> 	;
  2750                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2751                              <1>         ;  ((Modified registers: DX, CX))  
  2752                              <1> 
  2753                              <1> 	; 27/11/2021
  2754                              <1> 	; INPUT:
  2755                              <1> 	;	[cdev] = current device (root = 0, mounted = 1) 
  2756                              <1> 	;	eax = disk block/sector number/address (logical)
  2757                              <1> 	; OUTPUT:
  2758                              <1> 	;	ebx = superblock buffer address
  2759                              <1> 	;
  2760                              <1> 	;    Note:	
  2761                              <1> 	;	Free blocks map will be modified and written to it's disk.
  2762                              <1> 	;	Superblock (buffer) of [cdev] will be modified and it's 
  2763                              <1> 	;	modification flag will be set; but the superblock 
  2764                              <1> 	;	will not be written to it's disk in this 'free' procedure)
  2765                              <1> 	;
  2766                              <1> 	; Modified registers: ebx, ecx, edx, esi, edi, ebp 
  2767                              <1> 
  2768                              <1> 	; 27/11/2021
  2769 00005548 BB[14720000]        <1> 	mov 	ebx, systm ; (SuperBlock of root file system)
  2770 0000554D F605[15710000]01    <1> 	test	byte [cdev], 1
  2771 00005554 7405                <1> 	jz	short free_1
  2772 00005556 BB[1C740000]        <1> 	mov	ebx, mount ; (SuperBlock of mounted file system)
  2773                              <1> free_1: ; 1
  2774                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 file system compatibility code
  2775                              <1> 	;test	byte [ebx+SB.ReadOnly], 1 ; if bit 0 is 1, it is RO fs	
  2776                              <1> 	;jz	short free_2 
  2777                              <1> 	; 'read only file system' error
  2778 0000555B C705[AC710000]1E00- <1> 	mov	dword [u.error], ERR_READ_ONLY_FS
  2778 00005563 0000                <1>
  2779 00005565 E95DE7FFFF          <1> 	jmp	error
  2780                              <1> free_2:
  2781 0000556A 89C1                <1> 	mov	ecx, eax ; logical sector/block number
  2782 0000556C A3[24760000]        <1> 	mov	[free_map_sector], eax
  2783 00005571 C1E903              <1> 	shr	ecx, 3	; convert to fbmap byte offset
  2784 00005574 C1E80C              <1> 	shr	eax, 12 ; convert to fbmap sector index 
  2785                              <1> 			; (1 fb sector for 4096 sectors)
  2786                              <1> 	;and	cl, ~3	; dword alignment (to backward)
  2787 00005577 890D[1C760000]      <1> 	mov	[free_map_offset], ecx ; byte position on fbm
  2788                              <1> 	; 27/11/2021
  2789                              <1> 	; eax = fbm sector index
  2790 0000557D 034318              <1> 	add	eax, [ebx+SB.FreeMapAddr] 
  2791                              <1> 			; free blocks map start sector address
  2792                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2793                              <1> 	;		; + Hidden Sectors
  2794                              <1> 	; ebx = superblock address
  2795                              <1> 	; eax = physical sector number
  2796 00005580 E82B0C0000          <1> 	call	dskrd
  2797                              <1> 	; cpu returns here if there is/was not an error in 'dskrd'
  2798                              <1> 	; eax = physical sector number
  2799                              <1> 	; ebx = buffer data address
  2800                              <1> 	; 27/11/2021
  2801 00005585 A3[20760000]        <1> 	mov	[free_map_index], eax  ; save physical sector address
  2802 0000558A 8B15[1C760000]      <1> 	mov	edx, [free_map_offset] ; byte position on fbm
  2803                              <1> 	;
  2804 00005590 29C0                <1> 	sub	eax, eax
  2805 00005592 A0[24760000]        <1> 	mov	al, [free_map_sector] ; logical sector number
  2806 00005597 2407                <1> 	and	al, 7
  2807                              <1> 
  2808                              <1> 	; al = bit offset in fbm allocation byte
  2809                              <1> 	; edx = buffer address (start+offset)
  2810                              <1> 	; [free_map_offset] = byte position on fbm
  2811                              <1> 	; 27/11/2021
  2812 00005599 0FAB02              <1> 	bts	[edx], eax  ; copy value of bit position in eax to cf
  2813                              <1> 			    ; then set same bit position at [edx]
  2814 0000559C 7305                <1> 	jnc	short free_3 ; it was allocated sector
  2815                              <1> 
  2816                              <1> 	; already free sector !? 
  2817                              <1> 	; (nonsence or defective fs)
  2818                              <1> 
  2819 0000559E 30C0                <1> 	xor	al, al ; 0  ; eax = 0
  2820 000055A0 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2821                              <1> 	;mov	[ebx+SB.FreeBlocks], eax 
  2822                              <1> 		; invalidate free blocks count
  2823 000055A1 EB18                <1> 	jmp	short free_5
  2824                              <1> free_3:
  2825                              <1> 	; 27/11/2021
  2826 000055A3 8B4338              <1> 	mov	eax, [ebx+SB.FreeBlocks]
  2827 000055A6 40                  <1> 	inc	eax
  2828 000055A7 7401                <1> 	jz	short free_4 ; 0FFFFFFFFh -> 0 (invalid!)
  2829 000055A9 48                  <1> 	dec	eax  ; 0 -> 0FFFFFFFFh (invalid!)
  2830                              <1> free_4: 
  2831 000055AA 50                  <1> 	push	eax ; * ; number of free blocks 
  2832                              <1> 	;mov	eax, [free_map_index] ; fbm sector index
  2833                              <1> 	;add	eax, [ebx+SB.FreeMapAddr] 
  2834                              <1> 			; free blocks map start sector address
  2835                              <1> 	;add	eax, [ebx+SB.BootSectAddr]
  2836                              <1> 	;		; + Hidden Sectors
  2837 000055AB A1[20760000]        <1> 	mov	eax, [free_map_index] ; restore physical sector address
  2838                              <1> 	; eax = physical sector number
  2839 000055B0 E85B0C0000          <1> 	call	wslot
  2840                              <1> 	; ebx = buffer data address (write operation bit is set)
  2841                              <1> 	; eax = physical sector number
  2842                              <1> 	; Note: ebx contains addr of the 1st buffer in the buffer
  2843                              <1> 	; (the last allocated buffer becomes the 1st in buffer chain)
  2844                              <1> 
  2845 000055B5 E8720C0000          <1> 	call	dskwr ; writes the 1st buffer to sector
  2846                              <1> 		      ; (at the beginning/head of the buffer chain)
  2847                              <1> 
  2848                              <1> 	; if we are here, buffer has been written to disk successfully 
  2849                              <1> 	; (otherwise cpu would jump to 'error' address)
  2850 000055BA 58                  <1> 	pop	eax ; *  ; number of free blocks 
  2851                              <1> free_5:
  2852                              <1> 	; eax = number of free blocks 
  2853                              <1> 	;
  2854                              <1> 	; set superblock modified flag
  2855 000055BB BA[27710000]        <1> 	mov	edx, smod
  2856 000055C0 BB[14720000]        <1> 	mov	ebx, systm
  2857 000055C5 F605[15710000]01    <1> 	test	byte [cdev], 1 ; mounted device ?
  2858 000055CC 7406                <1> 	jz	short free_6 ; no, root device
  2859                              <1> 	; yes, mounted device
  2860 000055CE BB[1C740000]        <1> 	mov	ebx, mount
  2861                              <1> 	;mov	edx, mmod
  2862 000055D3 42                  <1> 	inc	edx ; edx = offset mmod
  2863                              <1> free_6: 
  2864 000055D4 894338              <1> 	mov	[ebx+SB.FreeBlocks], eax 
  2865                              <1> 
  2866 000055D7 A1[24760000]        <1> 	mov	eax, [free_map_sector] ; logical sector number
  2867 000055DC 3B433C              <1> 	cmp	eax, [ebx+SB.FirstFreeBlk]
  2868 000055DF 7303                <1> 	jnb	short free_7
  2869 000055E1 89433C              <1> 	mov	[ebx+SB.FirstFreeBlk], eax
  2870                              <1> free_7:
  2871 000055E4 FE02                <1> 	inc	byte [edx] ; superblock modified !
  2872 000055E6 C3                  <1> 	retn
  2873                              <1> 	
  2874                              <1> iget:
  2875                              <1> 	; 30/11/2021
  2876                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  2877                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2878                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2879                              <1> 	;
  2880                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2881                              <1> 	;
  2882                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2883                              <1> 	; 
  2884                              <1> 	; INPUTS ->
  2885                              <1> 	;    ii - current i-number, rootdir
  2886                              <1> 	;    cdev - new i-node device
  2887                              <1> 	;    idev - current i-node device
  2888                              <1> 	;    imod - current i-node modified flag
  2889                              <1> 	;    mnti - cross device file i-number
  2890                              <1> 	;    r1 - i-numbe rof new i-node
  2891                              <1> 	;    mntd - mountable device number		
  2892                              <1> 	; 	 
  2893                              <1> 	; OUTPUTS ->
  2894                              <1> 	;    cdev, idev, imod, ii, r1
  2895                              <1> 	;
  2896                              <1> 	; ((AX = R1)) input/output
  2897                              <1> 	;
  2898                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2899                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2900                              <1> 
  2901                              <1> 	; 22/11/2021
  2902                              <1> 	;;mov	dl, [cdev] ; 18/07/2013
  2903                              <1> 	;;mov	dh, [idev] ; 07/08/2013
  2904                              <1> 	; 26/05/2020 - Retro UNIX 386 v2
  2905                              <1> 	;mov	dh, [cdev]
  2906                              <1> 	;mov	dl, [idev]
  2907 000055E7 668B15[14710000]    <1> 	mov	dx, [idev] ; [idev] in dl, [cdev] in dh
  2908                              <1> 	;
  2909                              <1> 	; 22/11/2021
  2910 000055EE 25FFFF0000          <1> 	and	eax, 0FFFFh
  2911 000055F3 3B05[10710000]      <1> 	cmp 	eax, [ii]
  2912                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2913 000055F9 7504                <1> 	jne 	short iget_1
  2914                              <1> 		; bne 1f
  2915 000055FB 38F2                <1> 	cmp	dl, dh
  2916                              <1> 		; cmp idev,cdev
  2917                              <1> 			  ; / is device number of i-node = current device
  2918 000055FD 746C                <1>         je	short iget_5
  2919                              <1> 	;	; beq 2f
  2920                              <1> 	; 14/08/2021
  2921                              <1> iget_1: ; 1:
  2922 000055FF 30DB                <1> 	xor	bl, bl
  2923 00005601 381D[26710000]      <1> 	cmp	[imod], bl ; 0	
  2924                              <1> 		; tstb imod / has i-node of current file
  2925                              <1> 			  ; / been modified i.e., imod set
  2926 00005607 7628                <1> 	jna	short iget_2
  2927                              <1> 		; beq 1f
  2928 00005609 881D[26710000]      <1> 	mov	[imod], bl ; 0
  2929                              <1> 		;  clrb	imod / if it has, 
  2930                              <1> 			   ; / we must write the new i-node out on disk
  2931                              <1> 	; 22/11/2021 (32 bit push-pop)
  2932 0000560F 50                  <1> 	push	eax ; *
  2933                              <1> 		; mov r1,-(sp)
  2934 00005610 52                  <1> 	push	edx ; **
  2935                              <1> 		; mov cdev,-(sp)
  2936 00005611 A1[10710000]        <1> 	mov	eax, [ii]
  2937                              <1> 		; mov ii,r1
  2938                              <1> 	;mov	dh, [idev]
  2939 00005616 8835[15710000]      <1> 	mov	[cdev], dh
  2940                              <1> 		; mov idev,cdev
  2941 0000561C FEC3                <1> 	inc	bl ; 1
  2942                              <1> 	; 31/07/2013
  2943 0000561E 881D[08720000]      <1> 	mov     [rw], bl ; 1 == write 
  2944                              <1> 	;;28/07/2013 rw -> u.rw
  2945                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2946 00005624 E843000000          <1> 	call	icalc
  2947                              <1> 		; jsr r0,icalc; 1
  2948 00005629 5A                  <1> 	pop	edx ; **
  2949 0000562A 8835[15710000]      <1> 	mov	[cdev], dh ; 22/11/2021
  2950                              <1> 		; mov (sp)+,cdev
  2951 00005630 58                  <1> 	pop	eax ; *
  2952                              <1> 		; mov (sp)+,r1
  2953                              <1> iget_2: ; 1:
  2954                              <1> 	;and	ax, ax
  2955 00005631 21C0                <1> 	and	eax, eax ; 22/11/2021 (32 bit inode number)
  2956                              <1> 		; tst r1 / is new i-number non zero
  2957 00005633 7431                <1> 	jz	short iget_4 ; 2f
  2958                              <1> 		; beq 2f / branch if r1=0
  2959                              <1> 
  2960                              <1> 	;mov 	dh, [cdev]
  2961 00005635 08F6                <1> 	or	dh, dh ; 22/11/2021
  2962                              <1> 		; tst cdev / is the current device number non zero
  2963                              <1> 			 ; / (i.e., device =/ drum)
  2964 00005637 7515                <1> 	jnz	short iget_3 ;  1f
  2965                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2966                              <1> 	; 22/11/2021
  2967 00005639 3B05[20710000]      <1> 	cmp	eax, [mnti]
  2968                              <1> 	;cmp	ax, [mnti]			
  2969                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2970                              <1> 			    ; / file (root directory of mounted device)
  2971 0000563F 750D                <1> 	jne	short iget_3 ; 1f
  2972                              <1> 		; bne 1f
  2973                              <1>         ;mov    bl, [mntd]
  2974 00005641 FEC6                <1> 	inc	dh ; mov dh, 1 ; 22/11/2021
  2975 00005643 8835[15710000]      <1>         mov	[cdev], dh ; 22/11/2021
  2976                              <1> 		; mov mntd,cdev / make mounted device the current device
  2977                              <1> 	; 22/11/2021
  2978 00005649 A1[1C710000]        <1> 	mov	eax, [rootdir] ; rootdir = 1 (for runix v2 file system)
  2979                              <1> 	;mov	ax, [rootdir]
  2980                              <1> 		; mov rootdir,r1
  2981                              <1> iget_3: ; 1:
  2982                              <1> 	; 22/11/2021
  2983 0000564E A3[10710000]        <1> 	mov	[ii], eax ; 32 bit inode number
  2984                              <1> 	;mov	[ii], ax
  2985                              <1> 		; mov r1,ii
  2986                              <1> 	; 30/11/2021
  2987 00005653 8835[14710000]      <1> 	mov	[idev], dh ; cdev 
  2988                              <1> 	;mov	[idev], dl ; cdev
  2989                              <1> 		; mov cdev,idev
  2990 00005659 30DB                <1> 	xor	bl, bl
  2991                              <1>         ; 31/07/2013
  2992 0000565B 881D[08720000]      <1> 	mov     [rw], bl ; 0 == read 
  2993                              <1> 	;;28/07/2013 rw -> u.rw       
  2994                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2995 00005661 E806000000          <1> 	call	icalc
  2996                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2997                              <1> iget_4: ; 2:
  2998                              <1> 	; 22/11/2021
  2999 00005666 A1[10710000]        <1> 	mov	eax, [ii]
  3000                              <1> 	;mov	ax, [ii]
  3001                              <1> 		; mov ii,r1
  3002                              <1> iget_5:
  3003 0000566B C3                  <1> 	retn
  3004                              <1> 		; rts r0
  3005                              <1> 
  3006                              <1> icalc:
  3007                              <1> 	; 28/11/2021
  3008                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification 
  3009                              <1> 	; 02/07/2015
  3010                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3011                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3012                              <1> 	;
  3013                              <1> 	; calculate physical block number from i-number then
  3014                              <1> 	; read or write that block
  3015                              <1> 	;
  3016                              <1> 	; 'icalc' is called from 'iget'
  3017                              <1> 	;
  3018                              <1> 	; for original unix v1:
  3019                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  3020                              <1>        	; / (i+31.) mod 16. bytes from its start
  3021                              <1> 	;
  3022                              <1> 	; for retro unix 8086 v1:
  3023                              <1> 	;  i-node is located in block (i+47)/16 and
  3024                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  3025                              <1> 	;
  3026                              <1> 	; INPUTS ->
  3027                              <1> 	;    r1 - i-number of i-node
  3028                              <1> 	; 	 
  3029                              <1> 	; OUTPUTS ->
  3030                              <1> 	;    inode r/w
  3031                              <1> 	;
  3032                              <1> 	; ((AX = R1)) input
  3033                              <1> 	;
  3034                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  3035                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  3036                              <1> 	;
  3037                              <1> 
  3038                              <1> 	; 28/11/2021
  3039                              <1> 	;cmp	byte [idev], 0 ; [cdev] = [idev]
  3040 0000566C 803D[15710000]00    <1> 	cmp	byte [cdev], 0
  3041 00005673 7607                <1> 	jna	short icalc_0r
  3042 00005675 BD[1C740000]        <1> 	mov	ebp, mount  ; mounted file system's superblock 
  3043 0000567A EB05                <1> 	jmp	short icalc_0m
  3044                              <1> icalc_0r:
  3045                              <1> 	; 28/11/2021
  3046 0000567C BD[14720000]        <1> 	mov	ebp, systm  ; root file system's superblock 
  3047                              <1> icalc_0m:
  3048                              <1> 	; 22/11/2021
  3049                              <1> 	;mov	edx, eax
  3050 00005681 8B15[10710000]      <1> 	mov	edx, [ii] ; 32 bit inode number
  3051 00005687 8B4528              <1> 	mov	eax, [ebp+SB.InodeTblAddr] ; inode table base address
  3052                              <1> 	;
  3053 0000568A 4A                  <1> 	dec	edx ; 0 based inode number 
  3054                              <1> 		    ; (inode index in inode table)
  3055 0000568B 52                  <1> 	push	edx ; *
  3056 0000568C C1EA03              <1> 	shr	edx, 3
  3057 0000568F 7402                <1> 	jz	short icalc_0t ; 0 for inodes 1 to 8
  3058 00005691 01D0                <1> 	add	eax, edx
  3059                              <1> icalc_0t:
  3060                              <1> 	;add	eax, [ebp+SB.BootSectAddr]
  3061 00005693 E8180B0000          <1> 	call	dskrd
  3062                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  3063                              <1> 	; 31/07/2013
  3064 00005698 803D[08720000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  3065                              <1> 	;; 28/07/2013 rw -> u.rw
  3066                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  3067                              <1> 		; tst (r0)
  3068 0000569F 7605                <1> 	jna	short icalc_1
  3069                              <1> 		; beq 1f / branch to wslot when argument
  3070                              <1> 		       ; / in icalc call = 1
  3071                              <1> 	; eAX = r1  = block number
  3072 000056A1 E86A0B0000          <1> 	call	wslot
  3073                              <1> 		; jsr r0,wslot / set up data buffer for write
  3074                              <1> 			     ; / (will be same buffer as dskrd got)
  3075                              <1> 	; EBX = r5 points to first word in data area for this block
  3076                              <1> icalc_1: ; 1:
  3077 000056A6 5A                  <1> 	pop	edx ; *
  3078                              <1> 	; 22/11/2021
  3079 000056A7 83E207              <1> 	and 	edx, 07h ; 8 inodes per inode table sector
  3080 000056AA C1E206              <1> 	shl 	edx, 6 ; * 64 (inode size)
  3081                              <1> 	; edx = 64 * (mod(inodenumber-1)/8)
  3082 000056AD 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  3083 000056AF 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  3084                              <1>           	; eSI (r5) points to first word in i-node i.	
  3085                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  3086                              <1> 			     ; / 32.*(i+31.)mod16
  3087                              <1> 		; mov $5,lsh / for i-node i.
  3088                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  3089 000056B1 BF[D06D0000]        <1> 	mov	edi, inode
  3090                              <1> 		; mov $inode,r1 / inode is address of first word 
  3091                              <1> 			      ; / of current i-node
  3092                              <1> 	;mov 	ecx, 8 ; 02/07/2015 (32 bit modification)
  3093                              <1> 	;	; mov $16.,r3
  3094                              <1> 	; 28/11/2021
  3095 000056B6 29C9                <1> 	sub	ecx, ecx
  3096 000056B8 B110                <1> 	mov	cl, 16 ; Retro UNIX 386 v2 inode size = 64 bytes
  3097                              <1> 	; 31/07/2013
  3098 000056BA 382D[08720000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3099                              <1>        ;;28/07/2013 rw -> u.rw                 
  3100                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  3101                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  3102 000056C0 7609                <1> 	jna	short icalc_3
  3103                              <1> 		; beq 2f / r0 now contains proper return address 
  3104                              <1> 		       ; / for rts r0
  3105                              <1> icalc_2: ; 1:
  3106 000056C2 87F7                <1> 	xchg 	esi, edi
  3107                              <1> 	; overwrite old i-node (in buffer to be written)
  3108 000056C4 F3A5                <1> 	rep 	movsd
  3109                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  3110                              <1> 		; dec r3
  3111                              <1> 		; bgt 1b
  3112                              <1> 	;call	dskwr
  3113                              <1> 	;	; jsr r0,dskwr / write inode out on device
  3114                              <1> 	;retn
  3115                              <1> 	;	; rts r0
  3116                              <1> 	; 28/11/2021
  3117 000056C6 E9610B0000          <1> 	jmp	dskwr
  3118                              <1> icalc_3: ; 2:
  3119                              <1> 	; copy new i-node into inode area of (core) memory
  3120 000056CB F3A5                <1> 	rep 	movsd
  3121                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  3122                              <1> 		                ; / "inode" area of core
  3123                              <1> 		; dec r3
  3124                              <1> 		; bgt 2b
  3125 000056CD C3                  <1> 	retn
  3126                              <1> 		; rts r0
  3127                              <1> 
  3128                              <1> access:
  3129                              <1> 	; 25/12/2021
  3130                              <1> 	; 19/12/2021
  3131                              <1> 	; 28/11/2021
  3132                              <1> 	; 22/11/2021 - Retro UNIX 386 v2 compatibility modification
  3133                              <1> 	; 31/10/2021 - temporary (simplified code)
  3134                              <1> 	; 14/06/2021
  3135                              <1> 	; 02/05/2021
  3136                              <1> 	; 27/03/2021
  3137                              <1> 	; 26/03/2021
  3138                              <1> 	; 25/03/2021
  3139                              <1> 	; 23/03/2021 (Retro UNIX 386 v2 - Beginning)
  3140                              <1> 	;	((ref: unix v7 source - fio.c))
  3141                              <1> 	; ref: INODE STRUCTURE of Retro UNIX v2 file system
  3142                              <1> 	;	07/02/2020, 'RETRO UNIX v2 Inodes.pdf'
  3143                              <1> 	;	 
  3144                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3145                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3146                              <1> 	;
  3147                              <1> 	; check whether user is owner of file or user has read or write
  3148                              <1> 	; permission (based on i.flgs).
  3149                              <1> 	;
  3150                              <1> 	; INPUTS ->
  3151                              <1> 	;    r1 - i-number of file
  3152                              <1> 	;    u.uid
  3153                              <1> 	; arg0 -> (owner flag mask)	 		
  3154                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  3155                              <1> 	; OUTPUTS ->
  3156                              <1> 	;    inode (or jump to error)
  3157                              <1> 	;
  3158                              <1> 	; ((AX = R1)) input/output
  3159                              <1> 	;
  3160                              <1> 	;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))
  3161                              <1> 
  3162                              <1> 	; 26/03/2021
  3163                              <1> 	; INPUT:
  3164                              <1> 	;	eax = inode number (ax)
  3165                              <1> 	;	 dx = mode (IEXEC, IREAD or IWRITE) 
  3166                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3167                              <1> 	;	
  3168                              <1> 	; OUTPUT:
  3169                              <1> 	;	inode (or jump to error)
  3170                              <1> 	;	eax (ax) = [ii] = inode number
  3171                              <1> 	;	[cdev] = logical drive number ; 31/10/2021 
  3172                              <1> 	;
  3173                              <1> 	; Modified registers: (eax), ebx, ecx, edx, esi, edi, ebp
  3174                              <1> 	;
  3175                              <1> 	; IREAD	 equ 100h ; read permission flag, owner
  3176                              <1> 	; IWRITE equ 80h  ; write permission flag, owner
  3177                              <1> 	; IEXEC	 equ 40h  ; execute permission flag, owner	 
  3178                              <1> 		
  3179                              <1> 	; 23/03/2021
  3180 000056CE 52                  <1> 	push	edx ; save flag (DX)
  3181                              <1> 	;push	dx  ; save flag (DL)
  3182 000056CF E813FFFFFF          <1> 	call	iget
  3183                              <1> 		; jsr r0,iget / read in i-node for current directory
  3184                              <1> 			    ; / (i-number passed in r1)
  3185                              <1> 	;;mov	cl, [i.flgs]
  3186                              <1> 	;;	; mov i.flgs,r2
  3187                              <1> 	; 23/03/2021
  3188                              <1> 	;mov	cx, [i.iflgs]	
  3189                              <1> 
  3190                              <1> 	;;pop	dx  ; restore flag (DL)
  3191                              <1> 	; 23/03/2021
  3192 000056D4 5A                  <1> 	pop	edx ; restore flag (DX)
  3193                              <1> 
  3194                              <1> 	; 28/11/2021 (iget will not return here if there is an error)
  3195                              <1> 	; 31/10/2021
  3196                              <1> 	;jc	short access_5
  3197                              <1> 
  3198                              <1> 	; 31/10/2021
  3199                              <1> 	; Note: If eax input is same with [mnti], 'iget' will change
  3200                              <1> 	; [cdev] to 1 and eax will be 1 (root dir of mounted fs) 
  3201                              <1> 
  3202                              <1> 	; 27/03/2021
  3203                              <1> 	; 23/03/2021
  3204                              <1> 	; (check if it is write permission flag)
  3205 000056D5 6681FA8000          <1> 	cmp	dx, 80h ; IWRITE
  3206 000056DA 775E                <1> 	ja	short access_r	; IREAD = 100h (owner)
  3207 000056DC 722B                <1> 	jb	short access_x	; IEXEC = 40h (owner)
  3208                              <1> 	; IWRITE (80h)
  3209                              <1> access_w:
  3210                              <1> 	; 23/03/2021
  3211                              <1> 	; ((ref: Retro UNIX 386 v2, 'ux.s', 'ldrv' structure))
  3212                              <1> 	;mov	bl, [idev]
  3213                              <1> 	;call	getfs
  3214                              <1>  	;movzx	ebx, byte [idev]  ; logical drive number
  3215                              <1> 	;shl	bx, 6 ; * 64	  ; of current inode	
  3216                              <1> 	;add	ebx, ldrvtable	
  3217                              <1> 	;;test	byte [ebx+ldrv.pflags], 01h ; read only fs flag
  3218                              <1> 	;;jz	short access_0
  3219                              <1> 	;; 14/06/2021
  3220                              <1> 	; 14/06/2021
  3221                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3222                              <1> 	;mov	edi, [ebx+ldrv.superblk]
  3223                              <1> 	;test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3224                              <1> 	;jz	short access_0
  3225                              <1> 	; 31/10/2021
  3226 000056DE 803D[15710000]01    <1> 	cmp	byte [cdev], 1
  3227 000056E5 7207                <1> 	jb	short access_7 ; [cdev] = 0
  3228                              <1> 	; [cdev] = 1
  3229                              <1> 	; 28/11/2021
  3230 000056E7 BF[1C740000]        <1> 	mov	edi, mount ; mounted file system's superblock buffer
  3231 000056EC EB05                <1> 	jmp	short access_8
  3232                              <1> access_7:
  3233                              <1> 	; 28/11/2021
  3234 000056EE BF[14720000]        <1> 	mov	edi, systm ; root file system's superblock buffer
  3235                              <1> access_8:
  3236 000056F3 F6476A01            <1> 	test	byte [edi+SB.ReadOnly], 1 ; bit 0 = 1 ?
  3237 000056F7 7441                <1> 	jz	short access_0
  3238                              <1> 
  3239                              <1> 	; 23/03/2021
  3240                              <1> 	;mov	dword [u.error], ERR_READ_ONLY_FS
  3241                              <1> 	;		; 'read only file system !' error
  3242                              <1> 	;jmp	error
  3243                              <1> 
  3244                              <1> 	; 19/12/2021
  3245 000056F9 F605[D16D0000]80    <1> 	test	byte [i.flgs+1], 80h ; regular file ?
  3246 00005700 7438                <1> 	jz	short access_0  ; no, device file
  3247                              <1> 
  3248                              <1> 	; 31/10/2021
  3249 00005702 B81E000000          <1> 	mov	eax, ERR_READ_ONLY_FS
  3250                              <1> 			; 'read only file system !' error
  3251                              <1> 	; 27/03/2021
  3252 00005707 EB27                <1> 	jmp	short access_5
  3253                              <1> 
  3254                              <1> 	; check block device (fs) if it is read only fs or not ? 
  3255                              <1> 
  3256                              <1> 	;mov	dh, [u.uid]
  3257                              <1> 	;cmp	dh, [i.uid]
  3258                              <1> 	;	; cmpb i.uid,u.uid / is user same as owner of file
  3259                              <1> 	;jne	short access_1
  3260                              <1> 		; bne 1f / no, then branch
  3261                              <1> access_x:
  3262                              <1> 	; IEXEC (40h)
  3263                              <1> 	; 27/03/2021
  3264 00005709 668B1D[D06D0000]    <1> 	mov	bx, [i.flgs]
  3265 00005710 F6C780              <1> 	test	bh, 80h ; regular file ?
  3266 00005713 7416                <1> 	jz	short access_4 ; not executable file !
  3267 00005715 F6C740              <1> 	test	bh, 40h	; directory ?
  3268 00005718 7511                <1> 	jnz	short access_4 ; not executable file !
  3269 0000571A 668B0D[8A710000]    <1> 	mov	cx, [u.uid]
  3270 00005721 6609C9              <1> 	or	cx, cx
  3271 00005724 7520                <1> 	jnz	short access_3 ; (restricted user)
  3272                              <1> 	; (super user)
  3273                              <1> 	;test	[i.flgs], dl ; execute permission for owner
  3274                              <1> 	;test	byte [i.flgs], 49h ; for owner, group, others
  3275 00005726 F6C349              <1> 	test	bl, 49h ; exec perm for owner, group, others
  3276 00005729 7557                <1> 	jnz	short access_2
  3277                              <1> access_4:
  3278                              <1> 	; 31/10/2021
  3279 0000572B B816000000          <1> 	mov	eax, ERR_NOT_EXECUTABLE
  3280                              <1> 			; 'not executable file !' error
  3281                              <1> 	; 26/03/2021
  3282                              <1> ;;sysexec_not_exf:
  3283                              <1> ;	mov	dword [u.error], ERR_NOT_EXECUTABLE
  3284                              <1> ;			; 'not executable file !' error
  3285                              <1> ;access_5:
  3286                              <1> ;	jmp	error
  3287                              <1> 	
  3288                              <1> 	; 31/10/2021
  3289                              <1> access_5:
  3290 00005730 A3[AC710000]        <1> 	mov	[u.error], eax
  3291 00005735 E98DE5FFFF          <1> 	jmp	error
  3292                              <1> 
  3293                              <1> access_r:
  3294                              <1> 	; 27/03/2021
  3295                              <1> access_0:
  3296                              <1> 	; 23/03/2021
  3297 0000573A 668B0D[8A710000]    <1> 	mov	cx, [u.uid]
  3298 00005741 6609C9              <1> 	or	cx, cx ; 0 ; root ?
  3299                              <1> 	;jz	short access_2 ; yes
  3300                              <1> 	; 25/12/2021
  3301 00005744 742C                <1> 	jz	short access_1 ; yes
  3302                              <1> access_3:
  3303                              <1> 	; owner ?
  3304 00005746 8A1D[D66D0000]      <1> 	mov	bl, [i.gid]
  3305 0000574C 663B0D[D46D0000]    <1> 	cmp	cx, [i.uid]
  3306                              <1> 	;je	short access_1
  3307                              <1> 	; 02/05/2021
  3308 00005753 750E                <1> 	jne	short access_6
  3309                              <1> 	; check owner's group number/ID
  3310 00005755 3A1D[8E710000]      <1> 	cmp	bl, [u.gid] ; same group number/ID ?
  3311 0000575B 7415                <1> 	je	short access_1 ; yes, owner
  3312                              <1> 	; one of others
  3313 0000575D 66C1EA06            <1> 	shr	dx, 6
  3314 00005761 EB0F                <1> 	jmp	short access_1 ; others
  3315                              <1> access_6:
  3316                              <1> 	;shr	cl, 2
  3317                              <1> 	;	; asrb r2 / shift owner read write bits into non owner
  3318                              <1> 	;	;       ; / read/write bits
  3319                              <1> 	;	; asrb r2
  3320                              <1> 
  3321                              <1> 	; 23/03/2021
  3322                              <1> 	; same group ?
  3323 00005763 66C1EA03            <1> 	shr	dx, 3
  3324                              <1> 	;mov	cl, [u.gid]
  3325                              <1> 	;cmp	cl, [i.gid]
  3326                              <1> 	;je	short access_1
  3327                              <1> 	; 02/05/2021
  3328 00005767 3A1D[8E710000]      <1> 	cmp	bl, [u.gid]
  3329 0000576D 7403                <1> 	je	short access_1 ; same group, different owner
  3330                              <1> 
  3331                              <1> 	; others
  3332                              <1> 	;shr	dx, 3
  3333 0000576F C0EA03              <1> 	shr	dl, 3
  3334                              <1> 	;jmp	short access_1	
  3335                              <1> 
  3336                              <1> ;access_1: ; 1:
  3337                              <1> 	;and	cl, dl
  3338                              <1> 	;	; bit r2,(r0)+ / test read-write flags against argument
  3339                              <1> 	;		     ; / in access call
  3340                              <1> 	;jnz	short access_2
  3341                              <1> 	;	; bne 1f
  3342                              <1> 	
  3343                              <1> 	;or	dh, dh	; super user (root) ?
  3344                              <1> 	;	; tstb u.uid
  3345                              <1> 	;jz	short access_2 ; yes, super user
  3346                              <1> 	;;jnz	error
  3347                              <1> 	;	; beq 1f
  3348                              <1> 	;	; jmp error
  3349                              <1> 	
  3350                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3351                              <1> 	;		; 'permission denied !' error
  3352                              <1> 	;jmp	error
  3353                              <1> 
  3354                              <1> access_1:
  3355                              <1> 	; 23/03/2021
  3356 00005772 668515[D06D0000]    <1> 	test	dx, [i.flgs]
  3357 00005779 7507                <1> 	jnz	short access_2
  3358                              <1> 
  3359                              <1> 	;; r/w permission error
  3360                              <1> 	;mov	dword [u.error], ERR_FILE_ACCESS 
  3361                              <1> 	;		; 'permission denied !' error
  3362                              <1> 	;;jmp	error
  3363                              <1> 
  3364                              <1> 	; 31/10/2021
  3365 0000577B B80B000000          <1> 	mov	eax, ERR_FILE_ACCESS 
  3366                              <1> 			; 'permission denied !' error
  3367                              <1> 	; 27/03/2021
  3368 00005780 EBAE                <1> 	jmp	short access_5
  3369                              <1> 
  3370                              <1> access_2: ; 1:
  3371                              <1> 	;; DL = flags
  3372                              <1> 	;retn
  3373                              <1> 	;	; rts r0
  3374                              <1> 	; 27/03/2021
  3375                              <1> 	; DX = flag (100h-20h-04h or 80h-10h-02h or 40h-08h-01h)
  3376 00005782 C3                  <1> 	retn
  3377                              <1> 
  3378                              <1> setimod:
  3379                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3380                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3381                              <1> 	;
  3382                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  3383                              <1> 	; the inode has been modified. Also puts the time of modification
  3384                              <1> 	; into the inode.
  3385                              <1> 	;
  3386                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  3387                              <1>         ;  ((Modified registers: eDX, eCX, eBX)) 
  3388                              <1> 	;
  3389                              <1> 	
  3390                              <1> 	; push 	edx
  3391 00005783 50                  <1> 	push	eax
  3392                              <1> 
  3393 00005784 C605[26710000]01    <1> 	mov 	byte [imod], 1
  3394                              <1> 		; movb $1,imod / set current i-node modified bytes
  3395                              <1> 	; Erdogan Tan 14-7-2012
  3396 0000578B E860E0FFFF          <1> 	call 	epoch
  3397                              <1> 		 ; mov s.time,i.mtim 
  3398                              <1> 			    ; / put present time into file modified time
  3399                              <1> 		 ; mov s.time+2,i.mtim+2
  3400                              <1> 
  3401 00005790 A3[086E0000]        <1> 	mov 	[i.mtim], eax
  3402                              <1> 	
  3403                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  3404                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  3405 00005795 833D[0C6E0000]00    <1> 	cmp	dword [i.ctim], 0
  3406 0000579C 7505                <1> 	jnz	short setimod_ok
  3407                              <1> 
  3408 0000579E A3[0C6E0000]        <1> 	mov 	[i.ctim], eax
  3409                              <1> 
  3410                              <1> setimod_ok: ; 31/07/2013
  3411 000057A3 58                  <1> 	pop	eax
  3412                              <1> 	;pop	edx
  3413                              <1> 	
  3414 000057A4 C3                  <1> 	retn
  3415                              <1> 		; rts r0
  3416                              <1> 
  3417                              <1> itrunc:
  3418                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3419                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  3420                              <1> 	;
  3421                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  3422                              <1> 	;  to zero length.
  3423                              <1> 	;
  3424                              <1> 	; INPUTS ->
  3425                              <1> 	;    r1 - i-number of i-node
  3426                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  3427                              <1> 	;    i.flgs - large file flag		
  3428                              <1> 	;    i.size - size of file	
  3429                              <1> 	; 	 
  3430                              <1> 	; OUTPUTS ->
  3431                              <1> 	;    i.flgs - large file flag is cleared
  3432                              <1> 	;    i.size - set to 0	
  3433                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  3434                              <1> 	;    setimod - set to indicate i-node has been modified
  3435                              <1> 	;    r1 - i-number of i-node  					
  3436                              <1> 	;
  3437                              <1> 	; ((AX = R1)) input/output
  3438                              <1> 	;
  3439                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  3440                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  3441                              <1> 
  3442 000057A5 E83DFEFFFF          <1> 	call	iget
  3443                              <1> 		; jsr r0,iget
  3444 000057AA BE[DC6D0000]        <1> 	mov	esi, i.dskp
  3445                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  3446 000057AF 31C0                <1> 	xor	eax, eax
  3447                              <1> itrunc_1: ; 1:
  3448 000057B1 66AD                <1> 	lodsw
  3449                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  3450 000057B3 6609C0              <1> 	or 	ax, ax
  3451 000057B6 743B                <1> 	jz	short itrunc_5
  3452                              <1> 		; beq 5f
  3453 000057B8 56                  <1> 	push	esi
  3454                              <1> 		; mov r2,-(sp)
  3455 000057B9 66F705[D06D0000]00- <1> 	test    word [i.flgs], 1000h    
  3455 000057C1 10                  <1>
  3456                              <1> 		; bit $10000,i.flgs / test large file bit?
  3457 000057C2 7429                <1> 	jz	short itrunc_4
  3458                              <1> 		; beq 4f / if clear, branch
  3459 000057C4 50                  <1> 	push	eax
  3460                              <1> 		; mov r1,-(sp) / save block number of indirect block
  3461 000057C5 E8E6090000          <1> 	call	dskrd
  3462                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  3463                              <1> 			     ; / pointed to by r5
  3464                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  3465 000057CA B900010000          <1> 	mov	ecx, 256
  3466                              <1> 		; mov $256.,r3 / move word count into r3
  3467 000057CF 89DE                <1> 	mov	esi, ebx
  3468                              <1> itrunc_2: ; 2:
  3469 000057D1 66AD                <1> 	lodsw
  3470                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  3471                              <1> 			     ; / physical block number
  3472 000057D3 6621C0              <1> 	and	ax, ax
  3473 000057D6 7409                <1> 	jz	short itrunc_3
  3474                              <1> 		; beq 3f / branch if zero
  3475                              <1> 	;push	ecx
  3476 000057D8 6651                <1> 	push	cx
  3477                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  3478                              <1> 	;push	esi
  3479                              <1> 		; mov r5,-(sp)
  3480 000057DA E869FDFFFF          <1> 	call	free
  3481                              <1> 		; jsr r0,free / free block in free storage map
  3482                              <1> 	;pop	esi
  3483                              <1> 		; mov(sp)+,r5
  3484 000057DF 6659                <1> 	pop	cx
  3485                              <1> 	;pop	ecx
  3486                              <1> 		; mov (sp)+,r3
  3487                              <1> itrunc_3: ; 3:
  3488 000057E1 E2EE                <1> 	loop	itrunc_2
  3489                              <1> 		; dec r3 / decrement word count
  3490                              <1> 		; bgt 2b / branch if positive
  3491 000057E3 58                  <1> 	pop	eax
  3492                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3493                              <1> 			     ; / indirect block
  3494                              <1> 	; 01/08/2013
  3495 000057E4 668125[D06D0000]FF- <1>         and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3495 000057EC EF                  <1>
  3496                              <1> itrunc_4: ; 4:
  3497 000057ED E856FDFFFF          <1> 	call	free
  3498                              <1> 		; jsr r0,free / free indirect block
  3499 000057F2 5E                  <1> 	pop	esi
  3500                              <1> 		; mov (sp)+,r2
  3501                              <1> itrunc_5: ; 5:
  3502 000057F3 81FE[EC6D0000]      <1> 	cmp	esi, i.dskp+16
  3503                              <1> 		; cmp r2,$i.dskp+16.
  3504 000057F9 72B6                <1> 	jb	short itrunc_1	
  3505                              <1> 		; bne 1b / branch until all i.dskp entries check
  3506                              <1> 	; 01/08/2013
  3507                              <1> 	;and     word [i.flgs], 0EFFFh ; 1110111111111111b
  3508                              <1> 		; bic $10000,i.flgs / clear large file bit
  3509 000057FB BF[DC6D0000]        <1> 	mov	edi, i.dskp
  3510 00005800 66B90800            <1> 	mov	cx, 8
  3511 00005804 6631C0              <1> 	xor 	ax, ax
  3512 00005807 66A3[D86D0000]      <1> 	mov	[i.size], ax ; 0
  3513                              <1> 		; clr i.size / zero file size
  3514 0000580D F366AB              <1> 	rep	stosw
  3515                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3516                              <1> 			   ; / zero block pointers
  3517 00005810 E86EFFFFFF          <1> 	call	setimod
  3518                              <1> 		; jsr r0,setimod / set i-node modified flag
  3519 00005815 66A1[10710000]      <1> 	mov	ax, [ii]
  3520                              <1> 		; mov ii,r1
  3521 0000581B C3                  <1> 	retn
  3522                              <1> 		; rts r0
  3523                              <1> 
  3524                              <1> imap:
  3525                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3526                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3527                              <1> 	;
  3528                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3529                              <1> 	; allocation bit for an i-node whose number in r1.
  3530                              <1> 	;
  3531                              <1> 	; INPUTS ->
  3532                              <1> 	;    r1 - contains an i-number
  3533                              <1> 	;    fsp - start of table containing open files
  3534                              <1> 	;
  3535                              <1> 	; OUTPUTS ->
  3536                              <1> 	;    r2 - byte address of byte with the allocation bit
  3537                              <1> 	;    mq - a mask to locate the bit position.	
  3538                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3539                              <1> 	;
  3540                              <1> 	; ((AX = R1)) input/output
  3541                              <1> 	; ((DL/DX = MQ)) output
  3542                              <1> 	; ((BX = R2)) output
  3543                              <1> 	;
  3544                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3545                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3546                              <1> 	;
  3547                              <1> 		; / get the byte that has the allocation bit for 
  3548                              <1> 		; / the i-number contained in r1
  3549                              <1> 	;mov	dx, 1
  3550 0000581C B201                <1> 	mov	dl, 1
  3551                              <1> 		; mov $1,mq / put 1 in the mq
  3552 0000581E 0FB7D8              <1> 	movzx	ebx, ax
  3553                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3554                              <1>  		          ; / in the map we must find
  3555 00005821 6683EB29            <1> 	sub	bx, 41
  3556                              <1> 		; sub $41.,r2 / r2 has i-41
  3557 00005825 88D9                <1> 	mov	cl, bl
  3558                              <1> 		; mov r2,r3 / r3 has i-41
  3559 00005827 80E107              <1> 	and	cl, 7
  3560                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3561                              <1> 			   ; / the bit position
  3562 0000582A 7402                <1> 	jz	short imap1
  3563                              <1> 	;shl	dx, cl
  3564 0000582C D2E2                <1> 	shl	dl, cl
  3565                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3566                              <1> imap1:			   ; / to the left to mask the correct bit
  3567 0000582E 66C1EB03            <1> 	shr	bx, 3
  3568                              <1> 		; asr r2
  3569                              <1> 		; asr r2
  3570                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3571                              <1> 		       ; / from the start of the map
  3572                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3573 00005832 BE[14720000]        <1> 	mov	esi, systm
  3574                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3575                              <1> 				; / the super block for drum
  3576                              <1> 	;cmp	word [cdev], 0
  3577 00005837 803D[15710000]00    <1> 	cmp	byte [cdev], 0
  3578                              <1> 		; tst cdev / is the device the disk
  3579 0000583E 7606                <1> 	jna	short imap2
  3580                              <1> 		; beq 1f / yes
  3581 00005840 81C608020000        <1> 	add	esi, mount - systm
  3582                              <1> 		; add $mount-systm,r2 / for mounted device,
  3583                              <1> 			; / r2 points to 1st word of its super block
  3584                              <1> imap2: ; 1:
  3585 00005846 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3586                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3587 00005849 6683C304            <1> 	add	bx, 4
  3588 0000584D 01F3                <1> 	add	ebx, esi
  3589                              <1>         	; add (sp)+,r2 / ?
  3590                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3591                              <1> 		      ;; (2 + free map size + 2)
  3592                              <1> 		; add $2,r2 / ?
  3593                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3594                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3595 0000584F C3                  <1> 	retn
  3596                              <1> 		; rts r0
  2025                                  %include 'u6.s'      ; 31/05/2015
  2026                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2027                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2028                              <1> ; ****************************************************************************
  2029                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS6.INC
  2030                              <1> ; Last Modification: 31/12/2021
  2031                              <1> ; ----------------------------------------------------------------------------
  2032                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2033                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2034                              <1> ;
  2035                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2036                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2037                              <1> ; <Bell Laboratories (17/3/1972)>
  2038                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2039                              <1> ;
  2040                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2041                              <1> ;
  2042                              <1> ; ****************************************************************************
  2043                              <1> 
  2044                              <1> 	; 25/12/2021
  2045                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2046                              <1> readi:
  2047                              <1> 	; 20/05/2015
  2048                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2049                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2050                              <1> 	;
  2051                              <1> 	; Reads from an inode whose number in R1
  2052                              <1> 	; 
  2053                              <1> 	; INPUTS ->
  2054                              <1> 	;    r1 - inode number
  2055                              <1> 	;    u.count - byte count user desires
  2056                              <1> 	;    u.base - points to user buffer
  2057                              <1> 	;    u.fofp - points to word with current file offset
  2058                              <1> 	; OUTPUTS ->
  2059                              <1> 	;    u.count - cleared
  2060                              <1> 	;    u.nread - accumulates total bytes passed back
  2061                              <1> 	;
  2062                              <1> 	; ((AX = R1)) input/output
  2063                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2064                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2065                              <1> 
  2066 00005850 31D2                <1> 	xor	edx, edx ; 0
  2067 00005852 8915[64710000]      <1> 	mov 	[u.nread], edx ; 0
  2068                              <1> 		; clr u.nread / accumulates number of bytes transmitted
  2069 00005858 668915[A4710000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2070 0000585F 3915[60710000]      <1> 	cmp 	[u.count], edx ; 0
  2071                              <1> 		; tst u.count / is number of bytes to be read greater than 0
  2072 00005865 7701                <1> 	ja 	short readi_1 ; 1f
  2073                              <1> 		; bgt 1f / yes, branch
  2074 00005867 C3                  <1> 	retn
  2075                              <1> 		; rts r0 / no, nothing to read; return to caller
  2076                              <1> readi_1: ; 1:
  2077                              <1> 	;	; mov r1,-(sp) / save i-number on stack
  2078                              <1> 	;cmp	ax, 40
  2079                              <1> 	;	; cmp r1,$40. / want to read a special file 
  2080                              <1> 	;	;             / (i-nodes 1,...,40 are for special files)
  2081                              <1>         ;ja	dskr 
  2082                              <1> 	;	; ble 1f / yes, branch
  2083                              <1> 	;	; jmp dskr / no, jmp to dskr; 
  2084                              <1> 	;	;         / read file with i-node number (r1)
  2085                              <1> 	;	;    / starting at byte ((u.fofp)), read in u.count bytes
  2086                              <1> 	
  2087                              <1> 	; 28/11/2021
  2088 00005868 F605[AA710000]FF    <1> 	test	byte [u.kcall], 0FFh
  2089 0000586F 7505                <1> 	jnz	short readi_2  ; 'readi' called by 'namei'
  2090                              <1> 
  2091                              <1> 	; eax = inode number
  2092                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2093 00005871 E871FDFFFF          <1> 	call	iget
  2094                              <1> readi_2:
  2095                              <1> 	; 28/11/2021
  2096                              <1> 	; eax = inode number
  2097                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2098 00005876 E882040000          <1> 	call	is_regular_file
  2099                              <1> 	;jz	dskr ; regular file 
  2100                              <1> 	; 25/12/2021
  2101 0000587B 7505                <1> 	jnz	short readi_5 ; device file 
  2102                              <1> 	; regular file
  2103 0000587D E9E4000000          <1> 	jmp	dskr
  2104                              <1> readi_5:
  2105                              <1> 	; (20/05/2015)
  2106 00005882 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2107                              <1> 
  2108                              <1> 	; 28/11/2021	
  2109                              <1> 	; device file
  2110 00005883 BB[9D580000]        <1> 	mov	ebx, readi_4
  2111 00005888 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2112 0000588B 720E                <1> 	jb	short readi_3
  2113 0000588D 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2114 00005890 7709                <1> 	ja	short readi_3	
  2115                              <1> 	
  2116                              <1> 	; convert v2 inode number to v1 device inode number
  2117 00005892 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2118 00005894 89C1                <1> 	mov	ecx, eax
  2119 00005896 C0E102              <1> 	shl	cl, 2 ; * 4
  2120 00005899 01CB                <1> 	add	ebx, ecx
  2121                              <1> readi_3:
  2122 0000589B FF23                <1> 	jmp	dword [ebx]	
  2123                              <1> 		 ; jmp *1f-2(r1)
  2124                              <1> readi_4: ; 1:
  2125 0000589D [ED580000]          <1> 	dd	null ; 28/11/2021
  2126 000058A1 [F1580000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2127                              <1> 		 ;rtty / tty; r1=2
  2128                              <1> 		 ;rppt / ppt; r1=4
  2129 000058A5 [42590000]          <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 000058A9 [56600000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2142 000058AD [56600000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2143 000058B1 [56600000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2144 000058B5 [56600000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2145 000058B9 [56600000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2146 000058BD [56600000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2147 000058C1 [57590000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2148 000058C5 [3E590000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2149                              <1> 		 ;rcvt / tty0
  2150 000058C9 [3E590000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2151                              <1> 		 ;rcvt / tty1
  2152 000058CD [3E590000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2153                              <1> 		 ;rcvt / tty2
  2154 000058D1 [3E590000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2155                              <1> 		 ;rcvt / tty3
  2156 000058D5 [3E590000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2157                              <1> 		 ;rcvt / tty4
  2158 000058D9 [3E590000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2159                              <1> 		 ;rcvt / tty5
  2160 000058DD [3E590000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2161                              <1> 		 ;rcvt / tty6
  2162 000058E1 [3E590000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2163                              <1> 		 ;rcvt / tty7
  2164 000058E5 [3E590000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2165                              <1> 		 ;rcrd / crd
  2166 000058E9 [3E590000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2167                              <1> 
  2168                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2169                              <1> null:
  2170 000058ED 31C0                <1> 	xor	eax, eax
  2171 000058EF 58                  <1> 	pop	eax
  2172 000058F0 C3                  <1> 	retn
  2173                              <1> 
  2174                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2175                              <1> rtty: ; / read from console tty
  2176                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2177                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2178                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2179                              <1> 	;	     must be written immediate on video page (screen)
  2180                              <1> 	;	     when it is required.	
  2181                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2182                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2183                              <1> 	;
  2184                              <1> 	; Console tty buffer is PC keyboard buffer
  2185                              <1> 	; and keyboard-keystroke handling is different than original
  2186                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2187                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2188                              <1> 	;
  2189                              <1> 	; 06/12/2013
  2190 000058F1 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2191 000058F8 8A83[6F6E0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2192                              <1> rttys:
  2193                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2194                              <1> 	               ; / of the control and status block
  2195                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2196                              <1> 		       ; / tty buffer
  2197                              <1> 	; 28/07/2013
  2198 000058FE A2[6D710000]        <1> 	mov 	[u.ttyn], al
  2199                              <1> 	; 13/01/2014
  2200 00005903 FEC0                <1> 	inc	al
  2201 00005905 A2[6E710000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2202                              <1> rtty_nc: ; 01/02/2014
  2203                              <1> 	; 29/09/2013
  2204 0000590A B90A000000          <1> 	mov	ecx, 10
  2205                              <1> rtty_1: 	; 01/02/2014
  2206                              <1> 	;push 	cx ; 29/09/2013
  2207                              <1> 	; 11/12/2021
  2208 0000590F 51                  <1> 	push	ecx
  2209                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2210 00005910 B001                <1> 	mov 	al, 1
  2211 00005912 E8A10B0000          <1> 	call 	getc
  2212                              <1> 	;pop 	cx ; 29/09/2013	
  2213                              <1> 	; 11/12/2021
  2214 00005917 59                  <1> 	pop	ecx
  2215 00005918 7516                <1> 	jnz	short rtty_2
  2216                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2217                              <1> 	               ; / of chars. Is this number non-zero?
  2218 0000591A E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2219                              <1> 	; 05/10/2013
  2220 0000591C 8A25[6D710000]      <1> 	mov	ah, [u.ttyn]
  2221                              <1> 	; 29/09/2013
  2222 00005922 E80EF9FFFF          <1> 	call	sleep
  2223                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2224                              <1>                 ;           / (120 chars.)
  2225                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2226 00005927 EBE1                <1> 	jmp	short rtty_nc ; 01/02/2014
  2227                              <1> 
  2228                              <1> rtty_idle:
  2229                              <1> 	; 29/07/2013
  2230 00005929 E874F8FFFF          <1> 	call 	idle
  2231 0000592E EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2232                              <1> 	;1:
  2233                              <1> 		; tst 2(r5) / is the number of characters zero
  2234                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2235                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2236                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2237                              <1> 		          ; / contains the next char.
  2238                              <1> 		; dec 2(r5) / decrement the character count
  2239                              <1> rtty_2:
  2240 00005930 30C0                <1> 	xor 	al, al
  2241 00005932 E8810B0000          <1> 	call 	getc
  2242 00005937 E891000000          <1> 	call	passc
  2243                              <1> 		; jsr r0,passc / move the character to core (user)
  2244                              <1> 	;; 17/10/2015 - 16/07/2015
  2245                              <1> 	; 19/06/2014
  2246                              <1> 	;;jnz	short rtty_nc
  2247 0000593C 58                  <1> 	pop	eax  ; (20/05/2015)
  2248 0000593D C3                  <1> 	retn 
  2249                              <1> ;ret1:
  2250                              <1> 		; jmp ret / return to caller via 'ret'
  2251                              <1> 
  2252                              <1> rcvt:   ; < receive/read character from tty >
  2253                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2254                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2255                              <1> 	;
  2256                              <1> 	; Retro UNIX 8086 v1 modification !
  2257                              <1> 	; 
  2258                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2259                              <1> 	;		(exactly different than this one)
  2260                              <1> 	;	was in 'u9.s' file.
  2261                              <1> 	;
  2262 0000593E 2C0A                <1> 	sub 	al, 10
  2263                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2264                              <1> 	; 16/07/2013
  2265                              <1> 	; 21/05/2013
  2266 00005940 EBBC                <1>         jmp     short rttys
  2267                              <1>       
  2268                              <1> ;rppt: / read paper tape
  2269                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2270                              <1> ;			 / places
  2271                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2272                              <1> ;		       / also enables read bit in prs
  2273                              <1> ;	jsr	r0,passc / place character in users buffer area
  2274                              <1> ;	br	rppt
  2275                              <1> 
  2276                              <1> rmem: ; / transfer characters from memory to a user area of core
  2277                              <1> 	; 17/10/2015
  2278                              <1> 	; 11/06/2015
  2279                              <1> 	; 24/05/2015
  2280                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2281                              <1> 	;
  2282 00005942 8B35[48710000]      <1> 	mov     esi, [u.fofp]
  2283                              <1> rmem_1:
  2284 00005948 8B1E                <1>         mov     ebx, [esi]        
  2285                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2286                              <1> 		               ; / to be transferred to user
  2287 0000594A FF06                <1>         inc     dword [esi] ; 17/10/2015
  2288                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2289                              <1> 			    ; / char in memory file
  2290 0000594C 8A03                <1> 	mov	al, [ebx]
  2291                              <1> 		; movb (r1),r1 / get character from memory file, 
  2292                              <1> 		             ; / put it in r1
  2293 0000594E E87A000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2294                              <1> 			     ;  / the next byte of the users core area
  2295                              <1> 		; br rmem / continue
  2296 00005953 75F3                <1> 	jnz	short rmem_1
  2297                              <1> ret_:
  2298 00005955 58                  <1> 	pop	eax ; 09/06/2015
  2299 00005956 C3                  <1> 	retn
  2300                              <1> 
  2301                              <1> rlpr:
  2302                              <1> ;1:
  2303                              <1> ;rcrd:
  2304 00005957 C705[AC710000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2304 0000595F 0000                <1>
  2305 00005961 E961E3FFFF          <1> 	jmp	error
  2306                              <1> 		;jmp	error / see 'error' routine
  2307                              <1> 
  2308                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2309                              <1> dskr:
  2310                              <1> 	; 12/10/2015
  2311                              <1> 	; 21/08/2015
  2312                              <1> 	; 25/07/2015
  2313                              <1> 	; 10/07/2015
  2314                              <1> 	; 16/06/2015
  2315                              <1> 	; 31/05/2015
  2316                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2317                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2318                              <1> dskr_0:
  2319 00005966 50                  <1> 	push	eax
  2320                              <1> 		; mov (sp),r1 / i-number in r1
  2321                              <1> 	; AX = i-number
  2322 00005967 E87BFCFFFF          <1> 	call	iget
  2323                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2324                              <1>         ;movzx	edx, word [i.size] ; 16/06/2015
  2325                              <1> 	;	; mov i.size,r2 / file size in bytes in r2
  2326                              <1> 	; 28/11/2021
  2327 0000596C 8B15[D86D0000]      <1> 	mov	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2328                              <1> 	;
  2329 00005972 8B1D[48710000]      <1> 	mov	ebx, [u.fofp]
  2330 00005978 2B13                <1> 	sub	edx, [ebx]
  2331                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2332                              <1>         ; 12/10/2015
  2333                              <1> 	; jna	short ret_ 
  2334                              <1> 		; blos ret
  2335 0000597A 7709                <1> 	ja	short dskr_1
  2336                              <1> 	;
  2337                              <1> dskr_retn: ; 12/10/2015
  2338 0000597C 58                  <1> 	pop	eax
  2339 0000597D C605[AA710000]00    <1> 	mov	byte [u.kcall], 0
  2340 00005984 C3                  <1> 	retn	
  2341                              <1> dskr_1: 
  2342 00005985 3B15[60710000]      <1> 	cmp     edx, [u.count] 
  2343                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2344                              <1> 			       ; / to carry out read
  2345 0000598B 7306                <1> 	jnb	short dskr_2
  2346                              <1> 		; bhis 1f
  2347 0000598D 8915[60710000]      <1> 	mov	[u.count], edx
  2348                              <1> 		; mov r2,u.count / no, just read to end of file
  2349                              <1> dskr_2: ; 1:
  2350                              <1> 	; (E)AX = i-number ; 28/11/2021 (32 bit inode number)
  2351                              <1> 	;call	mget
  2352                              <1> 		; jsr r0,mget / returns physical block number of block 
  2353                              <1> 		    ; / in file where offset points
  2354                              <1> 	; 28/11/2021
  2355 00005993 E826F9FFFF          <1> 	call	mget_r
  2356                              <1> 
  2357                              <1> 	; eax = physical block number
  2358                              <1> 	; [cdev] = current device number 
  2359 00005998 E813080000          <1> 	call	dskrd
  2360                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2361                              <1> 			     ; / 1st word of data in buffer
  2362                              <1> 	; 09/06/2015
  2363 0000599D 803D[AA710000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2364 000059A4 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2365 000059A6 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0
  2366 000059AE 7705                <1> 	ja	short dskr_4
  2367                              <1> dskr_3:
  2368                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2369 000059B0 E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2370                              <1> dskr_4:
  2371                              <1> 	; EBX (r5) = system (I/O) buffer address -physical-
  2372 000059B5 E8C2020000          <1> 	call	sioreg
  2373                              <1> 		; jsr r0,sioreg
  2374 000059BA 87F7                <1> 	xchg	esi, edi
  2375                              <1> 	; edi = file (user data) offset
  2376                              <1> 	; edi = sector (I/O) buffer offset
  2377                              <1> 	; ecx = byte count
  2378 000059BC F3A4                <1> 	rep	movsb
  2379                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2380                              <1> 		                 ; / starting at u.base
  2381                              <1> 		; dec r3
  2382                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2383                              <1> 	; 25/07/2015
  2384                              <1> 	; eax = remain bytes in buffer
  2385                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2386 000059BE 09C0                <1> 	or	eax, eax
  2387 000059C0 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2388                              <1> 	; 03/08/2013
  2389                              <1> 	;pop	eax
  2390 000059C2 390D[60710000]      <1> 	cmp	[u.count], ecx ; 0
  2391                              <1> 		; tst u.count / all bytes read off disk
  2392                              <1> 		; bne dskr
  2393                              <1> 		; br ret
  2394                              <1>         ;ja	short dskr_0
  2395                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2396                              <1> 	;retn
  2397                              <1> 	; 12/10/2015
  2398 000059C8 76B2                <1> 	jna	short dskr_retn
  2399 000059CA 58                  <1> 	pop	eax  ; (i-node number)
  2400 000059CB EB99                <1> 	jmp	short dskr_0
  2401                              <1> 	
  2402                              <1> passc:
  2403                              <1> 	; 18/10/2015
  2404                              <1> 	; 10/07/2015
  2405                              <1> 	; 01/07/2015
  2406                              <1> 	; 08/06/2015
  2407                              <1> 	; 04/06/2015
  2408                              <1> 	; 20/05/2015
  2409                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2410                              <1> 	;
  2411                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2412                              <1> 	;		      to physical address
  2413 000059CD 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2414                              <1> 			     ; 1-4095 --> use previous physical base address
  2415                              <1> 			     ; in [u.pbase]
  2416 000059D5 7705                <1> 	ja	short passc_3
  2417                              <1> 	; 08/06/2015 - 10/07/2015
  2418 000059D7 E82C000000          <1> 	call	trans_addr_w
  2419                              <1> passc_3:
  2420                              <1> 	; 19/05/2015
  2421 000059DC 66FF0D[A4710000]    <1> 	dec	word [u.pcount]
  2422                              <1> 	;
  2423 000059E3 8B1D[A0710000]      <1> 	mov	ebx, [u.pbase]
  2424 000059E9 8803                <1> 	mov	[ebx], al
  2425                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2426                              <1> 		               ; / users buffer
  2427 000059EB FF05[5C710000]      <1> 	inc	dword [u.base]
  2428                              <1> 		; inc u.base / increment the pointer to point to 
  2429                              <1> 			  ; / the next byte in users buffer
  2430 000059F1 FF05[A0710000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2431 000059F7 FF05[64710000]      <1> 	inc	dword [u.nread]
  2432                              <1> 		; inc u.nread / increment the number of bytes read
  2433 000059FD FF0D[60710000]      <1> 	dec	dword [u.count]
  2434                              <1> 		; dec u.count / decrement the number of bytes to be read
  2435                              <1> 		; bne 1f / any more bytes to read? ; yes, branch
  2436 00005A03 C3                  <1> 	retn
  2437                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2438                              <1> 		             ; / 'readi' by:
  2439                              <1> 		;/ (1) pop the return address off the stack into r0
  2440                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2441                              <1> 	;1:
  2442                              <1> 		; clr	*$ps / clear processor status
  2443                              <1> 		; rts r0 / return to address currently on top of stack
  2444                              <1> 
  2445                              <1> trans_addr_r:
  2446                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2447                              <1> 	;	-'add_to_swap_queue' call is diasbled as temporary-
  2448                              <1> 	; Translate virtual address to physical address 
  2449                              <1> 	; for reading from user's memory space
  2450                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2451                              <1> 	; 18/10/2015
  2452                              <1> 	; 10/07/2015
  2453                              <1> 	; 09/06/2015
  2454                              <1> 	; 08/06/2015 
  2455                              <1> 	; 04/06/2015
  2456                              <1> 	;
  2457                              <1> 	; 18/10/2015
  2458 00005A04 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2459 00005A06 EB04                <1> 	jmp 	short trans_addr_rw
  2460                              <1> 
  2461                              <1> 	;push	eax
  2462                              <1> 	;push	ebx
  2463                              <1> 	;mov	ebx, [u.base]
  2464                              <1> 	;call	get_physical_addr ; get physical address
  2465                              <1> 	;;jnc	short cpass_0
  2466                              <1> 	;jnc	short passc_1
  2467                              <1> 	;mov	[u.error], eax
  2468                              <1> 	;;pop	ebx
  2469                              <1> 	;;pop	eax
  2470                              <1> 	;jmp	error
  2471                              <1> ;cpass_0:
  2472                              <1> 	; 18/10/2015
  2473                              <1> 	; 20/05/2015
  2474                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2475                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2476                              <1> 	;pop	ebx
  2477                              <1> 	;pop	eax
  2478                              <1> 	;retn	; 08/06/2015
  2479                              <1> 
  2480                              <1> trans_addr_w:
  2481                              <1> 	; 31/12/2021
  2482                              <1> 	; 30/11/2021 (Retro UNIX 386 v2, Retro UNIX 386 v1.2)
  2483                              <1> 	;	-'add_to_swap_queue' call is disabled as temporary-
  2484                              <1> 	; Translate virtual address to physical address
  2485                              <1> 	; for writing to user's memory space
  2486                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2487                              <1> 	; 18/10/2015
  2488                              <1> 	; 29/07/2015
  2489                              <1> 	; 10/07/2015
  2490                              <1> 	; 09/06/2015
  2491                              <1> 	; 08/06/2015
  2492                              <1> 	; 04/06/2015 (passc)
  2493                              <1> 	;
  2494                              <1> 	; 18/10/2015
  2495 00005A08 29D2                <1> 	sub	edx, edx
  2496 00005A0A FEC2                <1> 	inc	dl ; 1 (write access sign)
  2497                              <1> trans_addr_rw:
  2498 00005A0C 50                  <1> 	push	eax
  2499 00005A0D 53                  <1> 	push	ebx
  2500                              <1> 	; 18/10/2015
  2501 00005A0E 52                  <1> 	push 	edx ; r/w sign (in DL)
  2502                              <1> 	;
  2503 00005A0F 8B1D[5C710000]      <1> 	mov	ebx, [u.base]
  2504 00005A15 E842D9FFFF          <1> 	call	get_physical_addr ; get physical address
  2505 00005A1A 730A                <1> 	jnc	short passc_0
  2506 00005A1C A3[AC710000]        <1> 	mov	[u.error], eax
  2507                              <1> 	;pop	edx
  2508                              <1> 	;pop 	ebx
  2509                              <1> 	;pop	eax
  2510 00005A21 E9A1E2FFFF          <1> 	jmp	error
  2511                              <1> passc_0:
  2512 00005A26 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2513 00005A29 5A                  <1> 	pop	edx ; 18/10/2015
  2514 00005A2A 7517                <1> 	jnz	short passc_1
  2515                              <1> 	; 18/10/2015
  2516 00005A2C 20D2                <1> 	and 	dl, dl
  2517 00005A2E 7413                <1> 	jz	short passc_1
  2518                              <1> 	; 20/05/2015
  2519                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2520                              <1> 	; EBX = linear address
  2521 00005A30 51                  <1> 	push 	ecx
  2522                              <1> 	; 31/12/2021 - Retro UNIX 386 v1.2 (BugFix)
  2523 00005A31 53                  <1> 	push	ebx ;* ; BugFix  ; 31/12/2021
  2524 00005A32 E894D8FFFF          <1> 	call 	copy_page
  2525 00005A37 5B                  <1> 	pop	ebx ;* ; BugFix  ; 31/12/2021
  2526 00005A38 59                  <1> 	pop	ecx
  2527 00005A39 7217                <1> 	jc	short passc_2
  2528                              <1> 	; 30/11/2021
  2529                              <1> 	;push	eax ; physical address of the new/allocated page
  2530                              <1> 	;call	add_to_swap_queue
  2531                              <1> 	;pop	eax
  2532                              <1> 	; 18/10/2015
  2533 00005A3B 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2534                              <1> 	;mov 	ecx, PAGE_SIZE
  2535                              <1> 	;sub	ecx, ebx 
  2536 00005A41 01D8                <1> 	add	eax, ebx  
  2537                              <1> passc_1: 
  2538                              <1> 	; 18/10/2015
  2539                              <1> 	; 20/05/2015
  2540 00005A43 A3[A0710000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2541 00005A48 66890D[A4710000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2542 00005A4F 5B                  <1> 	pop	ebx
  2543 00005A50 58                  <1> 	pop	eax
  2544 00005A51 C3                  <1> 	retn	; 08/06/2015
  2545                              <1> passc_2:
  2546 00005A52 C705[AC710000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2546 00005A5A 0000                <1>
  2547                              <1> 	;pop 	ebx
  2548                              <1> 	;pop	eax
  2549 00005A5C E966E2FFFF          <1> 	jmp	error
  2550                              <1> 
  2551                              <1> 	; 25/12/2021
  2552                              <1> 	; 11/12/2021
  2553                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2554                              <1> writei:
  2555                              <1> 	; 20/05/2015
  2556                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2557                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2558                              <1> 	;
  2559                              <1> 	; Write data to file with inode number in R1
  2560                              <1> 	; 
  2561                              <1> 	; INPUTS ->
  2562                              <1> 	;    r1 - inode number
  2563                              <1> 	;    u.count - byte count to be written
  2564                              <1> 	;    u.base - points to user buffer
  2565                              <1> 	;    u.fofp - points to word with current file offset
  2566                              <1> 	; OUTPUTS ->
  2567                              <1> 	;    u.count - cleared
  2568                              <1> 	;    u.nread - accumulates total bytes passed back	
  2569                              <1> 	; ((AX = R1))
  2570                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2571                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2572                              <1> 
  2573 00005A61 31C9                <1> 	xor	ecx, ecx
  2574 00005A63 890D[64710000]      <1> 	mov 	[u.nread], ecx  ; 0
  2575                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2576                              <1> 		            ; / read or write calls
  2577 00005A69 66890D[A4710000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2578 00005A70 390D[60710000]      <1> 	cmp 	[u.count], ecx
  2579                              <1> 	;	; tst u.count / test the byte count specified by the user
  2580 00005A76 7701                <1> 	ja 	short writei_1 ; 1f
  2581                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2582 00005A78 C3                  <1> 	retn
  2583                              <1> 	;	; rts r0 / no, return - no writing to do
  2584                              <1> writei_1: ;1:
  2585                              <1> 	;	; mov r1 ,-(sp) / save the i-node number on the stack
  2586                              <1> 	;cmp 	ax, 40
  2587                              <1> 	;	; cmp r1,$40.
  2588                              <1> 	;	; / does the i-node number indicate a special file?
  2589                              <1>         ;ja	dskw 
  2590                              <1> 	;	; bgt dskw / no, branch to standard file output
  2591                              <1> 
  2592                              <1> 	; 28/11/2021
  2593 00005A79 F605[AA710000]FF    <1> 	test	byte [u.kcall], 0FFh
  2594 00005A80 7505                <1> 	jnz	short writei_2  ; 'writei' called by 'mkdir'
  2595                              <1> 
  2596                              <1> 	; eax = inode number
  2597                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2598 00005A82 E860FBFFFF          <1> 	call	iget
  2599                              <1> writei_2:
  2600                              <1> 	; 28/11/2021
  2601                              <1> 	; eax = inode number
  2602                              <1> 	; [cdev] = device number (0 = root fs, 1 = mounted fs)
  2603 00005A87 E871020000          <1> 	call	is_regular_file
  2604                              <1> 	;jz	dskw ; regular file 
  2605                              <1> 	; 25/12/2021
  2606 00005A8C 7505                <1> 	jnz	short writei_5 ; device file 
  2607                              <1> 	; regular file
  2608 00005A8E E9FD000000          <1> 	jmp	dskw
  2609                              <1> writei_5:
  2610                              <1> 	; (20/05/2015)
  2611 00005A93 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2612                              <1> 	
  2613                              <1> 	; 28/11/2021	
  2614                              <1> 	; device file
  2615 00005A94 BB[AE5A0000]        <1> 	mov	ebx, writei_4
  2616 00005A99 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2617 00005A9C 720E                <1> 	jb	short writei_3
  2618 00005A9E 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2619 00005AA1 7709                <1> 	ja	short writei_3 ; 11/12/2021	
  2620                              <1> 	
  2621                              <1> 	; convert v2 inode number to v1 device inode number
  2622 00005AA3 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2623 00005AA5 89C1                <1> 	mov	ecx, eax
  2624 00005AA7 C0E102              <1> 	shl	cl, 2 ; * 4
  2625 00005AAA 01CB                <1> 	add	ebx, ecx
  2626                              <1> writei_3:
  2627 00005AAC FF23                <1> 	jmp	dword [ebx]	
  2628                              <1> 		; jmp *1f-2(r1)
  2629                              <1> 		; / jump table and jump to the appropriate routine
  2630                              <1> writei_4: ;1:
  2631 00005AAE [ED580000]          <1> 	dd	null ; 28/11/2021
  2632 00005AB2 [FE5A0000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2633                              <1> 		 ;wtty / tty; r1=2
  2634                              <1> 		 ;wppt / ppt; r1=4
  2635 00005AB6 [605B0000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2636                              <1> 		 ;wmem / mem; r1=6
  2637                              <1> 		 ;wrf0 / rf0
  2638                              <1> 		 ;wrk0 / rk0
  2639                              <1> 		 ;wtap / tap0
  2640                              <1> 		 ;wtap / tap1
  2641                              <1> 		 ;wtap / tap2
  2642                              <1> 		 ;wtap / tap3
  2643                              <1> 		 ;wtap / tap4
  2644                              <1> 		 ;wtap / tap5
  2645                              <1> 		 ;wtap / tap6
  2646                              <1> 		 ;wtap / tap7
  2647 00005ABA [D8600000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2648 00005ABE [D8600000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2649 00005AC2 [D8600000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2650 00005AC6 [D8600000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2651 00005ACA [D8600000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2652 00005ACE [D8600000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2653 00005AD2 [515B0000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2654 00005AD6 [4B5B0000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2655                              <1> 		 ;xmtt / tty0
  2656 00005ADA [4B5B0000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2657                              <1> 		 ;xmtt / tty1
  2658 00005ADE [4B5B0000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2659                              <1> 		 ;xmtt / tty2
  2660 00005AE2 [4B5B0000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2661                              <1> 		 ;xmtt / tty3
  2662 00005AE6 [4B5B0000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2663                              <1> 		 ;xmtt / tty4
  2664 00005AEA [4B5B0000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2665                              <1> 		 ;xmtt / tty5
  2666 00005AEE [4B5B0000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2667                              <1> 		 ;xmtt / tty6
  2668 00005AF2 [4B5B0000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2669                              <1> 		 ;xmtt / tty7
  2670 00005AF6 [4B5B0000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2671                              <1> 		; / wlpr / lpr
  2672 00005AFA [4B5B0000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)
  2673                              <1> 
  2674                              <1> ;	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2675                              <1> ;null:
  2676                              <1> ;	xor	eax, eax
  2677                              <1> ;	pop	eax
  2678                              <1> ;	retn	
  2679                              <1> 
  2680                              <1> 	; 11/12/2021 - Retro UNIX 386 v1.2
  2681                              <1> wtty: ; write to console tty (write to screen)
  2682                              <1> 	; 18/11/2015
  2683                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2684                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2685                              <1> 	;
  2686                              <1> 	; Console tty output is on current video page
  2687                              <1> 	; Console tty character output procedure is changed here
  2688                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2689                              <1> 	;
  2690 00005AFE 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2691 00005B05 8AA3[6F6E0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2692 00005B0B 88E0                <1> 	mov	al, ah ; 07/07/2014
  2693                              <1> wttys:	
  2694                              <1> 	; 10/10/2013
  2695 00005B0D 8825[6D710000]      <1> 	mov 	[u.ttyn], ah
  2696                              <1> 	; 13/01/2014
  2697 00005B13 FEC0                <1> 	inc	al
  2698 00005B15 A2[6F710000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2699                              <1> wtty_nc: ; 15/05/2013
  2700                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2701 00005B1A E8FD000000          <1> 	call	cpass
  2702                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2703                              <1> 		             ; / none go to return address in syswrite
  2704                              <1> 		; tst r1 / is character = null
  2705                              <1> 		; beq wtty / yes, get next character
  2706                              <1> 	; 10/10/2013
  2707 00005B1F 7428                <1> 	jz	short wret
  2708                              <1> 	;1 :
  2709                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2710                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2711                              <1> 		;	          / than 20
  2712                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2713                              <1> 	; 27/06/2014
  2714                              <1> wtty_1:
  2715                              <1> 	; AH = tty number
  2716                              <1> 	; AL = ASCII code of the character
  2717                              <1> 	; 15/04/2014
  2718                              <1> 	;push	ax
  2719                              <1> 	; 11/12/2021
  2720 00005B21 50                  <1> 	push	eax
  2721 00005B22 E8FF090000          <1> 	call	putc ; 14/05/2013
  2722 00005B27 731D                <1> 	jnc	short wtty_2
  2723                              <1> 	; 18/11/2015
  2724 00005B29 E874F6FFFF          <1> 	call	idle
  2725                              <1> 	;mov	ax, [esp]
  2726                              <1> 	; 11/12/2021
  2727 00005B2E 8B0424              <1> 	mov	eax, [esp]
  2728 00005B31 E8F0090000          <1> 	call	putc
  2729 00005B36 730E                <1> 	jnc	short wtty_2 
  2730                              <1> 	; 02/06/2014
  2731 00005B38 8A25[6D710000]      <1> 	mov	ah, [u.ttyn]
  2732 00005B3E E8F2F6FFFF          <1> 	call	sleep
  2733                              <1> 	;pop	ax
  2734                              <1> 	; 11/12/2021
  2735 00005B43 58                  <1> 	pop	eax
  2736 00005B44 EBDB                <1> 	jmp 	short wtty_1
  2737                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2738                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2739                              <1> 			      ; / console tty and
  2740                              <1> 		; br 	2f / place character in list; if none available
  2741                              <1> 		   	  ; / branch to put process to sleep
  2742                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2743                              <1> wtty_2:
  2744                              <1> 	; 15/04/2014
  2745                              <1> 	;pop	ax
  2746                              <1> 	; 11/12/2021
  2747 00005B46 58                  <1> 	pop	eax
  2748 00005B47 EBD1                <1> 	jmp	short wtty_nc
  2749                              <1> 		; br wtty
  2750                              <1> wret:	; 10/10/2013 (20/05/2015)
  2751 00005B49 58                  <1> 	pop	eax
  2752 00005B4A C3                  <1> 	retn
  2753                              <1> 	;2:
  2754                              <1> 		;mov	r1,-(sp) / place character on stack
  2755                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2756                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2757                              <1> 		;br	1b / try again to place character in clist and output
  2758                              <1> 
  2759                              <1> xmtt:   ; < send/write character to tty >
  2760                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2761                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2762                              <1> 	;
  2763                              <1> 	; Retro UNIX 8086 v1 modification !
  2764                              <1> 	; 
  2765                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2766                              <1> 	;		(exactly different than this one)
  2767                              <1> 	;	was in 'u9.s' file.
  2768                              <1> 	;
  2769 00005B4B 2C0A                <1> 	sub 	al, 10
  2770                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2771                              <1> 	; 10/10/2013
  2772 00005B4D 88C4                <1> 	mov	ah, al
  2773                              <1> 	; 28/07/2013
  2774 00005B4F EBBC                <1> 	jmp	short wttys
  2775                              <1> 
  2776                              <1> ;wppt:
  2777                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2778                              <1> ;		         / if none return to writei's calling routine
  2779                              <1> ;	jsr	r0,pptoc / output character on ppt
  2780                              <1> ;	br	wppt
  2781                              <1> wlpr:
  2782 00005B51 C705[AC710000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2782 00005B59 0000                <1>
  2783 00005B5B E967E1FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2784                              <1> 		;/	jsr	r0,cpass
  2785                              <1> 		;/	cmp	r0,$'a
  2786                              <1> 		;/	blo	1f
  2787                              <1> 		;/	cmp	r1,$'z
  2788                              <1> 		;/	bhi	1f
  2789                              <1> 		;/	sub	$40,r1
  2790                              <1> 		;/1:
  2791                              <1> 		;/	jsr	r0,lptoc
  2792                              <1> 		;/	br	wlpr
  2793                              <1> 		; br rmem / continue
  2794                              <1> 
  2795                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2796                              <1> 	; 17/10/2015
  2797                              <1> 	; 11/06/2015
  2798                              <1> 	; 24/05/2015
  2799                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2800                              <1> 	;
  2801 00005B60 813D[11080000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2801 00005B66 [C5510000]          <1>
  2802 00005B6A 7415                <1>         je      short wmem_acc_err
  2803                              <1> 	;
  2804 00005B6C 8B35[48710000]      <1>         mov     esi, [u.fofp] 
  2805                              <1> wmem_1:
  2806 00005B72 E8A5000000          <1> 	call	cpass
  2807                              <1> 		; jsr r0,cpass / get next character from users area of
  2808                              <1> 			     ; / core and put it in r1
  2809                              <1>         	; mov r1,-(sp) / put character on the stack
  2810                              <1> 	; 20/09/2013
  2811 00005B77 74D0                <1> 	jz	short wret ; wmem_2  
  2812 00005B79 8B1E                <1>         mov     ebx, [esi]
  2813                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2814 00005B7B FF06                <1>         inc     dword [esi] ; 17/10/2015
  2815                              <1> 		; inc *u.fofp / increment file offset to point to next
  2816                              <1> 			    ; / available location in file
  2817 00005B7D 8803                <1> 	mov	[ebx], al	
  2818                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2819                              <1> 			        ; / assigned to it
  2820 00005B7F EBF1                <1> 	jmp	short wmem_1
  2821                              <1> 		; br wmem / continue
  2822                              <1> 	;1:
  2823                              <1> 	;jmp	error / ?
  2824                              <1> ;wmem_2:	
  2825                              <1> ;	; 20/09/2013
  2826                              <1> ;	pop	ax
  2827                              <1> ;	retn
  2828                              <1> 
  2829                              <1> wmem_acc_err:
  2830 00005B81 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2830 00005B89 0000                <1>
  2831 00005B8B E937E1FFFF          <1> 	jmp	error
  2832                              <1> 
  2833                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  2834                              <1> 
  2835                              <1> dskw: ; / write routine for non-special files
  2836                              <1> 	;
  2837                              <1> 	; 28/11/2021
  2838                              <1> 	; 25/07/2015
  2839                              <1> 	; 16/06/2015
  2840                              <1> 	; 09/06/2015
  2841                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2842                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2843                              <1> 
  2844                              <1> 	; 01/08/2013 (mkdir_w check)
  2845                              <1> 	;push	ax ; 26/04/2013
  2846                              <1> 	;	; mov (sp),r1 / get an i-node number from the stack into r1
  2847                              <1> 	; 28/11/2021
  2848 00005B90 50                  <1> 	push	eax
  2849                              <1> 	; AX = inode number
  2850 00005B91 E851FAFFFF          <1> 	call	iget
  2851                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2852                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2853 00005B96 8B1D[48710000]      <1>         mov     ebx, [u.fofp] 
  2854 00005B9C 8B13                <1> 	mov 	edx, [ebx]
  2855                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2856                              <1> 			       ; / in the fsp entry for this file] in r2
  2857 00005B9E 0315[60710000]      <1> 	add 	edx, [u.count]	
  2858                              <1> 		; add u.count,r2 / no. of bytes to be written
  2859                              <1> 			       ; / + file offset is put in r2
  2860                              <1> 	;; 16/06/2015        
  2861                              <1> 	;cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2862                              <1> 	;jna	short dskw_0
  2863                              <1> 	;mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2864                              <1> 	;jmp	error
  2865                              <1> dskw_0:	
  2866                              <1> 	; 28/11/2021
  2867 00005BA4 3B15[D86D0000]      <1> 	cmp	edx, [i.size] ; 32 bit file size (runix v2 inode)
  2868                              <1> 	;cmp	dx, [i.size]
  2869                              <1> 	;	; cmp r2,i.size / is this greater than the present size of
  2870                              <1> 		              ; / the file?
  2871 00005BAA 760B                <1> 	jna	short dskw_1
  2872                              <1> 		; blos 1f / no, branch
  2873 00005BAC 8915[D86D0000]      <1> 	mov	[i.size], edx ; 32 bit file size (runix v2 inode)
  2874                              <1> 	;mov	[i.size], dx
  2875                              <1> 	 	; mov r2,i.size / yes, increase the file size to 
  2876                              <1> 			      ; / file offset + no. of data bytes
  2877 00005BB2 E8CCFBFFFF          <1> 	call	setimod
  2878                              <1> 	 	; jsr r0,setimod / set imod=1 (i.e., core inode has been
  2879                              <1> 		          ; / modified), stuff time of modification into
  2880                              <1> 	          	  ; / core image of i-node
  2881                              <1> dskw_1: ; 1:
  2882                              <1> 	; 28/11/2021
  2883                              <1> 	;call	mget
  2884 00005BB7 E8F9F6FFFF          <1> 	call	mget_w
  2885                              <1> 	; EAX = Block number
  2886                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2887                              <1> 			    ; /	the next data byte
  2888                              <1> 	; eax = block number
  2889 00005BBC 8B1D[48710000]      <1> 	mov     ebx, [u.fofp]
  2890 00005BC2 8B13                <1> 	mov	edx, [ebx]
  2891 00005BC4 81E2FF010000        <1> 	and	edx, 1FFh  
  2892                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2893 00005BCA 750C                <1> 	jnz	short dskw_2
  2894                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2895                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2896 00005BCC 813D[60710000]0002- <1> 	cmp	dword [u.count], 512
  2896 00005BD4 0000                <1>
  2897                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2898                              <1> 				  ; / an entire block? (i.e., no. of
  2899 00005BD6 7305                <1> 	jnb	short dskw_3
  2900                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2901                              <1> 			; / Yes, branch. Don't have to read block
  2902                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2903                              <1>    		; / overwritten).
  2904 00005BD8 E8D3050000          <1> 	call	dskrd
  2905                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2906                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2907                              <1> dskw_3: ; 3:
  2908                              <1> 	; EAX (r1) = block/sector number
  2909 00005BDD E82E060000          <1> 	call	wslot
  2910                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2911                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2912 00005BE2 803D[AA710000]00    <1> 	cmp	byte [u.kcall], 0
  2913 00005BE9 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2914                              <1> 	;
  2915 00005BEB 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0
  2916 00005BF3 7705                <1> 	ja	short dskw_5
  2917                              <1> dskw_4:
  2918                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2919 00005BF5 E80AFEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2920                              <1> dskw_5:
  2921                              <1> 	; eBX (r5) = system (I/O) buffer address
  2922 00005BFA E87D000000          <1> 	call	sioreg
  2923                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2924                              <1> 			     ; / r1 = address of data, r2 points to location
  2925                              <1> 			     ; / in buffer in which to start writing data
  2926                              <1> 	; eSI = file (user data) offset
  2927                              <1> 	; eDI = sector (I/O) buffer offset
  2928                              <1> 	; eCX = byte count
  2929                              <1> 	;
  2930 00005BFF F3A4                <1>   	rep	movsb
  2931                              <1> 		; movb (r1 )+,(r2)+ 
  2932                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2933                              <1> 		; dec r3 / decrement no. of bytes to be written
  2934                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2935                              <1> 	; 25/07/2015
  2936                              <1> 	; eax = remain bytes in buffer
  2937                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2938 00005C01 09C0                <1> 	or	eax, eax
  2939 00005C03 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2940                              <1> dskw_6:
  2941 00005C05 E822060000          <1> 	call	dskwr
  2942                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2943 00005C0A 833D[60710000]00    <1>         cmp     dword [u.count], 0
  2944                              <1> 		; tst u.count / any more data to write?
  2945 00005C11 77A4                <1> 	ja	short dskw_1
  2946                              <1> 		; bne 1b / yes, branch
  2947                              <1> 	; 03/08/2013
  2948 00005C13 C605[AA710000]00    <1> 	mov	byte [u.kcall], 0
  2949                              <1> 	; 20/09/2013 (;;)
  2950                              <1> 	;pop	ax
  2951                              <1> 	; 28/11/2021
  2952 00005C1A 58                  <1> 	pop	eax  
  2953 00005C1B C3                  <1> 	retn
  2954                              <1> 	;;jmp 	short dskw_ret 
  2955                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2956                              <1> 
  2957                              <1> 	; 24/12/2021
  2958                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  2959                              <1> cpass: ; / get next character from user area of core and put it in r1
  2960                              <1> 	; 18/10/2015
  2961                              <1> 	; 10/10/2015
  2962                              <1> 	; 10/07/2015
  2963                              <1> 	; 02/07/2015
  2964                              <1> 	; 01/07/2015
  2965                              <1> 	; 24/06/2015
  2966                              <1> 	; 08/06/2015
  2967                              <1> 	; 04/06/2015
  2968                              <1> 	; 20/05/2015
  2969                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2970                              <1> 	;
  2971                              <1> 	; INPUTS -> 
  2972                              <1> 	;     [u.base] = virtual address in user area
  2973                              <1> 	;     [u.count] = byte count (max.)
  2974                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2975                              <1> 	; OUTPUTS -> 
  2976                              <1> 	;     AL = the character which is pointed by [u.base]
  2977                              <1> 	;     zf = 1 -> transfer count has been completed	
  2978                              <1>         ;
  2979                              <1> 	; ((Modified registers: EAX, EDX, ECX))
  2980                              <1> 	;
  2981                              <1> 	;
  2982 00005C1C 833D[60710000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2983                              <1> 		; tst u.count / have all the characters been transferred
  2984                              <1> 			    ; / (i.e., u.count, # of chars. left
  2985 00005C23 763F                <1> 	jna	short cpass_3
  2986                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2987 00005C25 FF0D[60710000]      <1> 	dec	dword [u.count]
  2988                              <1> 		; dec u.count / no, decrement u.count
  2989                              <1>         ; 19/05/2015 
  2990                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2991                              <1> 	;		      to physical address
  2992 00005C2B 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2993                              <1> 			     ; 1-4095 --> use previous physical base address
  2994                              <1> 			     ; in [u.pbase]
  2995 00005C33 770E                <1> 	ja	short cpass_1
  2996                              <1> 	; 02/07/2015
  2997 00005C35 833D[9C710000]00    <1> 	cmp	dword [u.ppgdir], 0  ; is the caller os kernel
  2998 00005C3C 7427                <1> 	je	short cpass_k 	; (sysexec, '/etc/init') ? 
  2999                              <1> 	; 08/06/2015 - 10/07/2015
  3000 00005C3E E8C1FDFFFF          <1> 	call	trans_addr_r
  3001                              <1> cpass_1:
  3002                              <1> 	; 02/07/2015
  3003                              <1> 	; 24/06/2015
  3004 00005C43 66FF0D[A4710000]    <1> 	dec	word [u.pcount]
  3005                              <1> cpass_2: 
  3006                              <1> 	; 10/10/2015
  3007                              <1> 	; 02/07/2015
  3008 00005C4A 8B15[A0710000]      <1> 	mov	edx, [u.pbase]
  3009 00005C50 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3010                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3011                              <1> 				; / by u.base and put it in r1
  3012 00005C52 FF05[64710000]      <1> 	inc	dword [u.nread]
  3013                              <1> 		; inc u.nread / increment no. of bytes transferred
  3014 00005C58 FF05[5C710000]      <1> 	inc	dword [u.base]
  3015                              <1> 		; inc u.base / increment the buffer address to point to the
  3016                              <1> 			   ; / next byte
  3017 00005C5E FF05[A0710000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3018                              <1> cpass_3:
  3019 00005C64 C3                  <1> 	retn
  3020                              <1> 		; rts	r0 / next byte
  3021                              <1> 	; 1: 
  3022                              <1> 		; mov (sp)+,r0 
  3023                              <1> 		         ; / put return address of calling routine into r0
  3024                              <1> 		; mov (sp)+,r1 / i-number in r1
  3025                              <1> 		; rts r0 / non-local return
  3026                              <1> cpass_k:
  3027                              <1> 	; 02/07/2015
  3028                              <1> 	; The caller is os kernel 
  3029                              <1> 	; (get sysexec arguments from kernel's memory space)
  3030                              <1> 	;
  3031 00005C65 8B1D[5C710000]      <1> 	mov	ebx, [u.base]
  3032 00005C6B 66C705[A4710000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3032 00005C73 10                  <1>
  3033 00005C74 891D[A0710000]      <1> 	mov	[u.pbase], ebx
  3034 00005C7A EBCE                <1> 	jmp	short cpass_2
  3035                              <1> 	
  3036                              <1> sioreg: 
  3037                              <1> 	; 25/07/2015
  3038                              <1> 	; 18/07/2015
  3039                              <1> 	; 02/07/2015
  3040                              <1> 	; 17/06/2015
  3041                              <1> 	; 09/06/2015
  3042                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3043                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3044                              <1> 	;
  3045                              <1> 	; INPUTS -> 
  3046                              <1> 	;     eBX = system buffer (data) address (r5)
  3047                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3048                              <1> 	;     [u.base] = virtual address of the user buffer
  3049                              <1> 	;     [u.pbase] = physical address of the user buffer
  3050                              <1> 	;     [u.count] = byte count
  3051                              <1> 	;     [u.pcount] = byte count within page frame 			
  3052                              <1> 	; OUTPUTS -> 
  3053                              <1> 	;     eSI = user data offset (r1)
  3054                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3055                              <1> 	;     eCX = byte count (r3)
  3056                              <1> 	;     EAX = remain bytes after byte count within page frame
  3057                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3058                              <1>         ;
  3059                              <1> 	; ((Modified registers:  EDX))
  3060                              <1>  
  3061 00005C7C 8B35[48710000]      <1>         mov     esi, [u.fofp]
  3062 00005C82 8B3E                <1>         mov     edi, [esi]
  3063                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3064 00005C84 89F9                <1> 	mov	ecx, edi
  3065                              <1> 		; mov r2,r3 / and also to r3
  3066 00005C86 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3067                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3068 00005C8C 81E7FF010000        <1> 	and	edi, 1FFh
  3069                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3070 00005C92 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3071                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3072                              <1> 			  ; / where data is to be placed
  3073                              <1>                 ; mov u.base,r1 / address of data is in r1
  3074 00005C94 F7D9                <1> 	neg	ecx
  3075                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3076                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3077 00005C96 3B0D[60710000]      <1> 	cmp	ecx, [u.count]
  3078                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3079                              <1> 			       ; / to be written to the file
  3080 00005C9C 7606                <1> 	jna	short sioreg_0
  3081                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3082                              <1> 			 ; / in the file block as the number to be written
  3083 00005C9E 8B0D[60710000]      <1> 	mov	ecx, [u.count]
  3084                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3085                              <1> 			       ; / bytes as the number to be written
  3086                              <1> sioreg_0:
  3087                              <1> 	; 17/06/2015
  3088 00005CA4 803D[AA710000]00    <1> 	cmp	byte [u.kcall], 0 
  3089 00005CAB 7613                <1> 	jna	short sioreg_1
  3090                              <1> 	; 25/07/2015
  3091                              <1> 	 ; the caller is 'mkdir' or 'namei'
  3092 00005CAD A1[5C710000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3093 00005CB2 A3[A0710000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3094 00005CB7 66890D[A4710000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3095 00005CBE EB0B                <1> 	jmp	short sioreg_2
  3096                              <1> sioreg_1:
  3097                              <1> 	; 25/07/2015
  3098                              <1> 	; 18/07/2015
  3099                              <1> 	; 09/06/2015 
  3100 00005CC0 0FB715[A4710000]    <1> 	movzx	edx, word [u.pcount]
  3101                              <1> 		; ecx and [u.pcount] are always > 0, here
  3102 00005CC7 39D1                <1> 	cmp	ecx, edx	
  3103 00005CC9 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3104                              <1> sioreg_2: ; 2:
  3105 00005CCB 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3106                              <1> sioreg_3:
  3107 00005CCD 010D[64710000]      <1> 	add 	[u.nread], ecx
  3108                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3109                              <1> 			         ; / during write is put into u.nread
  3110 00005CD3 290D[60710000]      <1> 	sub 	[u.count], ecx
  3111                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3112                              <1> 			       ; / must be written or read
  3113 00005CD9 010D[5C710000]      <1> 	add 	[u.base], ecx
  3114                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3115                              <1> 			      ; / data bytes
  3116 00005CDF 010E                <1>         add 	[esi], ecx 
  3117                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3118                              <1> 			       ; / + old file offset
  3119                              <1> 	; 25/07/2015
  3120 00005CE1 8B35[A0710000]      <1> 	mov	esi, [u.pbase]
  3121 00005CE7 66290D[A4710000]    <1> 	sub	[u.pcount], cx
  3122 00005CEE 010D[A0710000]      <1> 	add	[u.pbase], ecx
  3123 00005CF4 C3                  <1>         retn
  3124                              <1> 		; rts r0
  3125                              <1> 		; transfer count > [u.pcount]
  3126                              <1> sioreg_4:
  3127                              <1> 	; 25/07/2015
  3128                              <1> 	; transfer count > [u.pcount] 
  3129                              <1> 	; (ecx > edx)
  3130 00005CF5 89C8                <1> 	mov	eax, ecx
  3131 00005CF7 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3132 00005CF9 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3133 00005CFB EBD0                <1> 	jmp	short sioreg_3
  3134                              <1> 
  3135                              <1> 	; 28/11/2021 - Retro UNIX 386 v2 fs compatibility modification
  3136                              <1> is_regular_file:
  3137                              <1> 	; check if it is a regular file or device file inode
  3138                              <1> 	;
  3139                              <1> 	; INPUT:
  3140                              <1> 	;	current inode
  3141                              <1> 	; OUTPUT:
  3142                              <1> 	;	cf = 0 and zf = 1 -> regular file
  3143                              <1> 	;	cf = 0 and zf = 0 -> device file
  3144                              <1> 	;	cf = 1 -> invalid file (jump to 'error')
  3145                              <1> 	;
  3146                              <1> 	; Modified registers: ecx (cl)
  3147                              <1> 
  3148                              <1> 	; 28/11/2021
  3149 00005CFD 8A0D[D16D0000]      <1> 	mov	cl, [i.flgs+1]
  3150 00005D03 F6C180              <1> 	test	cl, 80h		; regular file ?
  3151 00005D06 7514                <1> 	jnz	short isregf_1  ; yes 
  3152 00005D08 80E120              <1> 	and	cl, 20h 	; device file ?
  3153 00005D0B 7511                <1> 	jnz	short isregf_2  ; yes 
  3154                              <1> 
  3155                              <1> 	; 28/11/2021
  3156                              <1> 	; invalid inode/file type !
  3157 00005D0D C705[AC710000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  3157 00005D15 0000                <1>
  3158                              <1> 	;stc
  3159                              <1> 	;retn
  3160 00005D17 E9ABDFFFFF          <1> 	jmp	error
  3161                              <1> isregf_1:
  3162 00005D1C 30C9                <1> 	xor	cl, cl  ; cl = 0
  3163                              <1> 	; zf = 1
  3164                              <1> 	;retn
  3165                              <1> isregf_2:
  3166                              <1> 	; zf = 0
  3167                              <1> 	; cl = 20h
  3168 00005D1E C3                  <1> 	retn	
  2026                                  %include 'u7.s'      ; 18/04/2015
  2027                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2028                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2029                              <1> ; ****************************************************************************
  2030                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS7.INC
  2031                              <1> ; Last Modification: 05/12/2021
  2032                              <1> ; ----------------------------------------------------------------------------
  2033                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2034                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2035                              <1> ;
  2036                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2037                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2038                              <1> ; <Bell Laboratories (17/3/1972)>
  2039                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2040                              <1> ;
  2041                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2042                              <1> ;
  2043                              <1> ; ****************************************************************************
  2044                              <1> 
  2045                              <1> sysmount: ; / mount file system; args special; name
  2046                              <1> 	; 14/11/2015
  2047                              <1> 	; 24/10/2015
  2048                              <1> 	; 13/10/2015
  2049                              <1> 	; 10/07/2015
  2050                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2051                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2052                              <1> 	;
  2053                              <1> 	; 'sysmount' anounces to the system that a removable 
  2054                              <1> 	; file system has been mounted on a special file.
  2055                              <1> 	; The device number of the special file is obtained via
  2056                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2057                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2058                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2059                              <1> 	; to read file system into core, i.e. the first block on the
  2060                              <1> 	; mountable file system is read in. This block is super block
  2061                              <1> 	; for the file system. This call is super user restricted.	
  2062                              <1> 	;
  2063                              <1> 	; Calling sequence:
  2064                              <1> 	;	sysmount; special; name
  2065                              <1> 	; Arguments:
  2066                              <1> 	;	special - pointer to name of special file (device)
  2067                              <1> 	;	name -  pointer to name of the root directory of the
  2068                              <1> 	;		newly mounted file system. 'name' should 
  2069                              <1> 	;		always be a directory.
  2070                              <1> 	; Inputs: - 
  2071                              <1> 	; Outputs: -
  2072                              <1> 	; ...............................................................
  2073                              <1> 	;				
  2074                              <1> 	; Retro UNIX 8086 v1 modification: 
  2075                              <1> 	;       'sysmount' system call has two arguments; so,
  2076                              <1> 	;	* 1st argument, special is pointed to by BX register
  2077                              <1> 	;	* 2nd argument, name is in CX register
  2078                              <1> 	;
  2079                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2080                              <1> 	;	       already modified for IBM PC compatibility and 
  2081                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2082                              <1> 	
  2083                              <1> 	;call	arg2
  2084                              <1> 		; jsr r0,arg2 / get arguments special and name
  2085 00005D1F 891D[50710000]      <1> 	mov	[u.namep], ebx
  2086 00005D25 51                  <1> 	push	ecx ; directory name
  2087 00005D26 66833D[20710000]00  <1> 	cmp	word [mnti], 0
  2088                              <1> 		; tst mnti / is the i-number of the cross device file
  2089                              <1> 			 ; / zero?
  2090                              <1> 	;ja	error
  2091                              <1>         	; bne errora / no, error
  2092 00005D2E 0F87E9000000        <1> 	ja	sysmnt_err0
  2093                              <1> 	;
  2094 00005D34 E8CC000000          <1> 	call	getspl
  2095                              <1> 		; jsr r0,getspl / get special files device number in r1
  2096                              <1> 	; 13/10/2015
  2097 00005D39 0FB7D8              <1> 	movzx	ebx, ax ; ; Retro UNIX 8086 v1 device number (0 to 5)
  2098 00005D3C F683[7A6B0000]80    <1>         test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2099 00005D43 750F                <1> 	jnz	short sysmnt_1
  2100                              <1> sysmnt_err1:
  2101 00005D45 C705[AC710000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2101 00005D4D 0000                <1>
  2102 00005D4F E973DFFFFF          <1> 	jmp	error
  2103                              <1> sysmnt_1:
  2104 00005D54 8F05[50710000]      <1> 	pop	dword [u.namep]
  2105                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2106                              <1> 				  ; / on the device
  2107                              <1> 	; 14/11/2015
  2108 00005D5A 53                  <1> 	push	ebx ; 13/10/2015
  2109                              <1> 		; mov r1,-(sp) / save the device number
  2110                              <1>         ;
  2111 00005D5B E8F4EEFFFF          <1> 	call	namei
  2112                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2113                              <1> 		       ; ax = 0 -> file not found 	
  2114                              <1> 	;jz	error
  2115                              <1> 	;jc	error
  2116                              <1> 		; jsr r0,namei / get the i-number of the file
  2117                              <1>                	; br errora
  2118 00005D60 730F                <1> 	jnc	short sysmnt_2
  2119                              <1> sysmnt_err2:
  2120 00005D62 C705[AC710000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2120 00005D6A 0000                <1>
  2121 00005D6C E956DFFFFF          <1> 	jmp	error
  2122                              <1> sysmnt_2:	
  2123 00005D71 66A3[20710000]      <1> 	mov	[mnti], ax
  2124                              <1>         	; mov r1,mnti / put it in mnti
  2125                              <1> ;	mov	ebx, sb1 ; super block buffer (of mounted disk)
  2126                              <1> sysmnt_3: ;1:
  2127                              <1>         ;cmp	byte [ebx+1], 0
  2128                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2129                              <1> 			   ; / dismountable device set?
  2130                              <1>         ;jna	short sysmnt_4		
  2131                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2132                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2133                              <1> 	;jmp	short sysmnt_3
  2134                              <1> sysmnt_4:   
  2135 00005D77 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2136 00005D78 A2[17710000]        <1> 	mov	[mdev], al
  2137                              <1> 		; mov  (sp),mntd / no, put the device number in mntd
  2138 00005D7D 8803                <1> 	mov	[ebx], al
  2139                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2140                              <1> 			      ; / of the I/O queue entry
  2141                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2142                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2143 00005D7F 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2144                              <1> 		; bis $2000,sb1 / set the read bit
  2145                              <1> 	; Retro UNIX 386 v1 modification : 
  2146                              <1> 	;	32 bit block number at buffer header offset 4
  2147 00005D84 C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2148 00005D8B E8E0050000          <1> 	call 	diskio
  2149 00005D90 731C                <1> 	jnc	short sysmnt_5
  2150 00005D92 31C0                <1> 	xor 	eax, eax
  2151 00005D94 66A3[20710000]      <1> 	mov	[mnti], ax ; 0
  2152 00005D9A A2[17710000]        <1> 	mov	[mdev], al ; 0
  2153                              <1> 	;mov	[cdev], al ; 0
  2154                              <1> sysmnt_invd:
  2155                              <1> 	; 14/11/2015
  2156 00005D9F FEC8                <1> 	dec 	al
  2157 00005DA1 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2158 00005DA3 FEC0                <1> 	inc	al
  2159 00005DA5 48                  <1> 	dec	eax
  2160 00005DA6 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2161 00005DA9 E919DFFFFF          <1> 	jmp	error
  2162                              <1> sysmnt_5:
  2163                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2164                              <1> 	; (Following check is needed to prevent mounting an
  2165                              <1> 	; in valid valid file system (in valid super block).
  2166                              <1> 	; 
  2167 00005DAE 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2168 00005DB1 C0E002              <1> 	shl	al, 2 ; 4*index
  2169 00005DB4 8B88[5E6B0000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2170 00005DBA C1E103              <1> 	shl 	ecx, 3
  2171 00005DBD 0FB715[18740000]    <1> 	movzx	edx, word [sb1+4] ; the 1st data word
  2172 00005DC4 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2173                              <1> 			 ; (in sectors), if they are not equal
  2174                              <1> 			 ; the disk to be mounted is an...	
  2175 00005DC6 75D7                <1> 	jne	short sysmnt_invd ; invalid disk !
  2176                              <1> 			 ; (which has not got a valid super block)
  2177                              <1> 	;
  2178 00005DC8 C6430100            <1> 	mov	byte [ebx+1], 0
  2179                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2180                              <1> ;sysmnt_6: ;1:
  2181                              <1> 	;;cmp	byte [sb1+1], 0
  2182                              <1> 		; tstb   sb1+1 / done reading?
  2183                              <1>    	;;jna	sysret
  2184                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2185                              <1> 	;;jmp	short sysmnt_6
  2186                              <1> 		;bne 1b / no, wait
  2187                              <1>         	;br sysreta / yes
  2188 00005DCC E916DFFFFF          <1> 	jmp	sysret
  2189                              <1> 
  2190                              <1> sysumount: ; / special dismount file system
  2191                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2192                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2193                              <1> 	;
  2194                              <1> 	; 04/11/2013
  2195                              <1> 	; 09/07/2013
  2196                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2197                              <1> 	; indicated as an argument is no longer contain a removable
  2198                              <1> 	; file system. 'getspl' gets the device number of the special
  2199                              <1> 	; file. If no file system was mounted on that device an error
  2200                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2201                              <1> 	; to 'sysret'.
  2202                              <1> 	;
  2203                              <1> 	; Calling sequence:
  2204                              <1> 	;	sysmount; special
  2205                              <1> 	; Arguments:
  2206                              <1> 	;	special - special file to dismount (device)
  2207                              <1> 	;
  2208                              <1> 	; Inputs: - 
  2209                              <1> 	; Outputs: -
  2210                              <1> 	; ...............................................................
  2211                              <1> 	;				
  2212                              <1> 	; Retro UNIX 8086 v1 modification: 
  2213                              <1> 	;       'sysumount' system call has one argument; so,
  2214                              <1> 	;	* Single argument, special is pointed to by BX register
  2215                              <1> 	;
  2216                              <1> 	
  2217                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2218                              <1> 	;call	arg
  2219                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2220 00005DD1 891D[50710000]      <1>         mov	[u.namep], ebx
  2221 00005DD7 E829000000          <1> 	call	getspl
  2222                              <1> 		; jsr r0,getspl / get the device number in r1
  2223 00005DDC 3A05[17710000]      <1> 	cmp	al, [mdev]
  2224                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2225 00005DE2 7539                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2226                              <1> 	;jne	error
  2227                              <1>         	; bne errora / no error
  2228 00005DE4 30C0                <1> 	xor	al, al ; ah = 0
  2229                              <1> sysumnt_0: ;1:
  2230 00005DE6 3805[15740000]      <1>      	cmp 	[sb1+1], al ; 0
  2231                              <1> 		; tstb sb1+1 / yes, is the device still doing I/O 
  2232                              <1> 			   ; / (inhibit bit set)?
  2233 00005DEC 7607                <1> 	jna	short sysumnt_1		
  2234                              <1> 		; bne 1b / yes, wait
  2235 00005DEE E8AFF3FFFF          <1> 	call	idle ; (wait for hardware interrupt)
  2236 00005DF3 EBF1                <1> 	jmp	short sysumnt_0
  2237                              <1> sysumnt_1:        
  2238 00005DF5 A2[17710000]        <1> 	mov	[mdev], al
  2239                              <1> 	     	; clr mntd / no, clear these
  2240 00005DFA 66A3[20710000]      <1>    	mov	[mnti], ax
  2241                              <1>         	; clr mnti
  2242 00005E00 E9E2DEFFFF          <1>         jmp	sysret
  2243                              <1> 		; br sysreta / return
  2244                              <1> 
  2245                              <1> getspl: ; / get device number from a special file name
  2246 00005E05 E84AEEFFFF          <1> 	call	namei
  2247                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2248                              <1> 		       ; ax = 0 -> file not found 	
  2249 00005E0A 0F8252FFFFFF        <1>         jc      sysmnt_err2 ; 'file not found !' error
  2250                              <1> 	;jz	error
  2251                              <1> 	;jc	error
  2252                              <1> 		; jsr r0,namei / get the i-number of the special file
  2253                              <1>                 ; br errora / no such file
  2254 00005E10 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2255                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2256                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2257 00005E14 7207                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2258                              <1> 	;jc	error
  2259                              <1> 		; ble errora / less than 0?  yes, error
  2260 00005E16 6683F805            <1>         cmp	ax, 5 ;
  2261                              <1> 		; cmp  r1,$9. / greater than 9  tap 7
  2262 00005E1A 7701                <1> 	ja	short sysmnt_err0 ; 'permission denied !' error
  2263                              <1> 	;ja	error
  2264                              <1>         	; bgt errora / yes, error
  2265                              <1>         ; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2266                              <1> iopen_retn:
  2267 00005E1C C3                  <1> 	retn
  2268                              <1> 		; rts    r0 / return with device number in r1
  2269                              <1> sysmnt_err0:
  2270 00005E1D C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2270 00005E25 0000                <1>
  2271 00005E27 E99BDEFFFF          <1> 	jmp	error
  2272                              <1> 
  2273                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2274                              <1> iopen:
  2275                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2276                              <1> 	; 27/03/2021 (Retro UNIX 386 v2)
  2277                              <1> 	; 19/05/2015
  2278                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2279                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2280                              <1> 	;
  2281                              <1> 	; open file whose i-number is in r1
  2282                              <1> 	; 
  2283                              <1> 	; INPUTS ->
  2284                              <1> 	;    r1 - inode number
  2285                              <1> 	; OUTPUTS ->
  2286                              <1> 	;    file's inode in core	
  2287                              <1> 	;    r1 - inode number (positive)
  2288                              <1> 	;
  2289                              <1> 	; ((AX = R1))
  2290                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2291                              <1> 	;        
  2292                              <1> ; / open file whose i-number is in r1
  2293                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2294                              <1> ;		;tst r1 / write or read access?
  2295                              <1> ;       jnz	short iopen_2
  2296                              <1> ;		;blt 2f / write, go to 2f
  2297                              <1> ;	mov	dl, 2 ; read access
  2298                              <1> ;	call	access
  2299                              <1> ;       	; jsr r0,access; 2 
  2300                              <1> ;	; / get inode into core with read access
  2301                              <1> ;	; DL=2
  2302                              <1> ;iopen_0:
  2303                              <1> ;       cmp	ax, 40
  2304                              <1> ;		; cmp r1,$40. / is it a special file
  2305                              <1> ;       ja	short iopen_retn
  2306                              <1> ;		;bgt  3f / no. 3f
  2307                              <1> 
  2308                              <1> 	; 05/12/2021
  2309                              <1> 	; DL = 0 -> open for read
  2310                              <1> 	; DL = 1 -> open for write
  2311                              <1> 
  2312 00005E2C 52                  <1> 	push	edx ; *
  2313                              <1> 
  2314                              <1> 	; set permission/mode flag for 'access' 
  2315                              <1> 	;	(DX = 100h -> IREAD, DX = 80h -> IWRITE)
  2316                              <1> 
  2317 00005E2D B601                <1> 	mov	dh, 1
  2318 00005E2F 08D2                <1> 	or	dl, dl ; dl = 0, open for read	
  2319 00005E31 7404                <1> 	jz	short iopen_0 ; DX = IREAD (100h)
  2320                              <1> 	; dl = 1, open for write 
  2321 00005E33 FECE                <1> 	dec	dh
  2322 00005E35 B280                <1> 	mov	dl, 80h
  2323                              <1> 	; DX = IWRITE (80h)
  2324                              <1> iopen_0:
  2325                              <1> 	; 27/03/2021
  2326                              <1> 	;   EAX = inode number (in AX)
  2327                              <1> 	;    DX = access mode, 100h = read, 80h = write
  2328                              <1> 
  2329                              <1> 	; 24/06/2020 - Retro UNIX 386 v2	
  2330 00005E37 E892F8FFFF          <1> 	call	access
  2331                              <1> 		;jsr r0,access; 1 / get inode in core
  2332                              <1> 	
  2333                              <1> 	; 27/03/2021
  2334                              <1> 	; DX return value from 'access' subroutine
  2335                              <1> 	;    may be 100h, 20h, 04h for DX = 100h (IREAD) input
  2336                              <1> 	;	     80h, 10h, 02h for DX = 80h (IWRITE) input
  2337                              <1> 
  2338                              <1> 	; 05/12/2021
  2339 00005E3C 5A                  <1> 	pop	edx ; * ; dl = 0 -> open for read
  2340                              <1> 			; dl = 1 -> open for write
  2341                              <1> 	; 24/06/2020
  2342 00005E3D 8A0D[D16D0000]      <1> 	mov	cl, [i.flgs+1]
  2343                              <1> 
  2344 00005E43 F6C180              <1> 	test	cl, 80h		; regular file ?
  2345 00005E46 7514                <1> 	jnz	short iopen_1	; yes ; 05/12/2021
  2346 00005E48 F6C120              <1> 	test	cl, 20h 	; device file ?
  2347 00005E4B 7524                <1> 	jnz	short iopen_2	; yes
  2348                              <1> 
  2349                              <1> 	; no !?, error.
  2350                              <1> 
  2351 00005E4D C705[AC710000]FF00- <1> 	mov	dword [u.error], ERR_INV_FILE ; 0FFh ; invalid file
  2351 00005E55 0000                <1>
  2352                              <1> iopen_err:
  2353 00005E57 E96BDEFFFF          <1> 	jmp	error
  2354                              <1> 
  2355                              <1> iopen_1:
  2356                              <1> 	; 05/12/2021
  2357                              <1> 	; (If open mode is 'write' and the file/inode is a directory,
  2358                              <1> 	;  open request will/must be rejected.)
  2359                              <1> 	;
  2360                              <1> 	; (If inode is a regular file and it is not a directory,
  2361                              <1> 	; there is nothing to do here, we need to return to 'sysopen'
  2362                              <1> 	; for completing the rest of file opening procedure.) 
  2363                              <1> 	
  2364 00005E5C F6C140              <1> 	test	cl, 40h	; directory ?
  2365 00005E5F 74BB                <1> 	jz	short iopen_retn ; no
  2366                              <1> 	
  2367 00005E61 20D2                <1> 	and	dl, dl ; open mode is 1 (write) ?
  2368 00005E63 74B7                <1> 	jz	short iopen_retn ; no
  2369                              <1> 
  2370                              <1> 	; !!!	
  2371                              <1> 	; 'sysopen' for writing
  2372                              <1> 	;	 is not applicable for directories
  2373                              <1> 	; (Directory entries must be created or deleted by
  2374                              <1> 	; relevant system calls.)
  2375                              <1> 
  2376                              <1> 	;mov	dword [u.error], ERR_DIR_ACCESS ; 11
  2377 00005E65 C705[AC710000]0B00- <1> 	mov	dword [u.error], ERR_PERM_DENIED ; 11
  2377 00005E6D 0000                <1>
  2378                              <1> 				; 'permission denied !' error  
  2379                              <1> 	;jmp	error
  2380 00005E6F EBE6                <1> 	jmp	short iopen_err
  2381                              <1> 
  2382                              <1> ;iopen_retn:
  2383                              <1> ;	retn
  2384                              <1> 
  2385                              <1> iopen_2:
  2386                              <1> 	;push	ax
  2387                              <1> 	;	; mov r1,-(sp) / yes, figure out
  2388                              <1> 	;movzx	ebx, al
  2389                              <1> 	;shl	bx, 2
  2390                              <1> 	;	; asl r1
  2391                              <1>         ;add	ebx, iopen_1 - 4
  2392                              <1> 	;jmp	dword [ebx]
  2393                              <1>         ;	; jmp *1f-2(r1) / which one and transfer to it
  2394                              <1> 	
  2395                              <1> 	; 05/12/2021
  2396 00005E71 50                  <1> 	push	eax ; save inode number
  2397                              <1> 	; device file
  2398 00005E72 BB[8E5E0000]        <1> 	mov	ebx, iopen_4
  2399 00005E77 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2400 00005E7A 720E                <1> 	jb	short iopen_3
  2401 00005E7C 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2402 00005E7F 7709                <1> 	ja	short iopen_3	
  2403                              <1> 	; convert v2 inode number to v1 device inode number
  2404 00005E81 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2405 00005E83 89C1                <1> 	mov	ecx, eax
  2406 00005E85 C0E102              <1> 	shl	cl, 2 ; * 4
  2407 00005E88 01CB                <1> 	add	ebx, ecx
  2408                              <1> iopen_3:
  2409 00005E8A FEC2                <1> 	inc	dl ; 1 = read, 2 = write
  2410 00005E8C FF23                <1> 	jmp	dword [ebx]	
  2411                              <1> 		 ; jmp *1f-2(r1)
  2412                              <1> ;iopen_1: ; 1:
  2413                              <1> iopen_4:
  2414 00005E8E [ED580000]          <1> 	dd	null ; 05/12/2021
  2415 00005E92 [DE5E0000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2416                              <1>  		 ;otty / tty ; r1=2
  2417                              <1>         	 ;oppt / ppt ; r1=4
  2418 00005E96 [7C5F0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2419                              <1> 		 ;sret / mem ; r1=6
  2420                              <1> 		 ;sret / rf0
  2421                              <1>         	 ;sret / rk0
  2422                              <1>         	 ;sret / tap0
  2423                              <1>         	 ;sret / tap1
  2424                              <1>         	 ;sret / tap2
  2425                              <1>         	 ;sret / tap3
  2426                              <1>         	 ;sret / tap4
  2427                              <1>         	 ;sret / tap5
  2428                              <1>         	 ;sret / tap6
  2429                              <1>         	 ;sret / tap7
  2430 00005E9A [7C5F0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2431 00005E9E [7C5F0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2432 00005EA2 [7C5F0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2433 00005EA6 [7C5F0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2434 00005EAA [7C5F0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2435 00005EAE [7C5F0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2436                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2437 00005EB2 [7C5F0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2438 00005EB6 [ED5E0000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2439                              <1> 		 ;ocvt / tty0
  2440 00005EBA [ED5E0000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2441                              <1> 		 ;ocvt / tty1
  2442 00005EBE [ED5E0000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2443                              <1> 		 ;ocvt / tty2
  2444 00005EC2 [ED5E0000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2445                              <1> 		 ;ocvt / tty3
  2446 00005EC6 [ED5E0000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2447                              <1> 		 ;ocvt / tty4
  2448 00005ECA [ED5E0000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2449                              <1> 		 ;ocvt / tty5
  2450 00005ECE [ED5E0000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2451                              <1> 		 ;ocvt / tty6
  2452 00005ED2 [ED5E0000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2453                              <1> 		 ;ocvt / tty7
  2454 00005ED6 [ED5E0000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2455                              <1> 		 ;error / crd
  2456 00005EDA [ED5E0000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2457                              <1> 
  2458                              <1> ;iopen_2: ; 2: / check open write access
  2459                              <1> ;	neg	ax
  2460                              <1> ;		;neg r1 / make inode number positive
  2461                              <1> ;	mov	dl, 1 ; write access
  2462                              <1> ;	call	access
  2463                              <1> ;		;jsr r0,access; 1 / get inode in core
  2464                              <1> ;	; DL=1
  2465                              <1> ;	test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2466                              <1> ;		;bit $40000,i.flgs / is it a directory?
  2467                              <1> ;	jz	short iopen_0
  2468                              <1> ;	;mov	[u.error], ERR_DIR_ACCESS
  2469                              <1> ;	;jmp	error ; permission denied !
  2470                              <1> ;	jmp	sysmnt_err0
  2471                              <1> ;	;;jnz	error		
  2472                              <1> ;      		; bne 2f / yes, transfer (error)
  2473                              <1> ;       ;;jmp     short iopen_0
  2474                              <1> ;	;cmp	ax, 40
  2475                              <1> ;		; cmp r1,$40. / no, is it a special file?
  2476                              <1> ;        ;ja	short iopen_2
  2477                              <1> ;		 ;bgt 3f / no, return
  2478                              <1> ;	;push	ax
  2479                              <1> ;		;mov r1,-(sp) / yes
  2480                              <1> ;	;movzx	ebx, al
  2481                              <1> ;	;shl	bx, 1
  2482                              <1> ;		; asl r1
  2483                              <1> ;	;add	ebx, ipen_3 - 2
  2484                              <1> ;	;jmp	dword [ebx]
  2485                              <1> ;		; jmp *1f-2(r1) / figure out 
  2486                              <1> ;			; / which special file it is and transfer
  2487                              <1> ;iopen_3: ; 1:
  2488                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2489                              <1> ; 		 ;otty / tty ; r1=2
  2490                              <1> ;        	 ;leadr / ppt ; r1=4
  2491                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2492                              <1> ;		 ;sret / mem ; r1=6
  2493                              <1> ;		 ;sret / rf0
  2494                              <1> ;        	 ;sret / rk0
  2495                              <1> ;        	 ;sret / tap0
  2496                              <1> ;        	 ;sret / tap1
  2497                              <1> ;        	 ;sret / tap2
  2498                              <1> ;        	 ;sret / tap3
  2499                              <1> ;        	 ;sret / tap4
  2500                              <1> ;        	 ;sret / tap5
  2501                              <1> ;        	 ;sret / tap6
  2502                              <1> ;        	 ;sret / tap7
  2503                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2504                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2505                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2506                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2507                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2508                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2509                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2510                              <1> ;	;dd	ejec ; lpr, AX = 9  (runix)
  2511                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2512                              <1> ;		 ;ocvt / tty0
  2513                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2514                              <1> ;		 ;ocvt / tty1
  2515                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2516                              <1> ;		 ;ocvt / tty2
  2517                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2518                              <1> ;		 ;ocvt / tty3
  2519                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2520                              <1> ;		 ;ocvt / tty4
  2521                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2522                              <1> ;		 ;ocvt / tty5
  2523                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2524                              <1> ;		 ;ocvt / tty6
  2525                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2526                              <1> ;		 ;ocvt / tty7
  2527                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2528                              <1> ;		 ;/ ejec / lpr
  2529                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2530                              <1> 
  2531                              <1> otty: ;/ open console tty for reading or writing
  2532                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2533                              <1> 	; 16/11/2015
  2534                              <1> 	; 12/11/2015
  2535                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2536                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2537                              <1> 	; 16/07/2013
  2538                              <1> 	; Retro UNIX 8086 v1 modification:
  2539                              <1> 	;  If a tty is open for read or write by
  2540                              <1> 	;     a process (u.uno), only same process can open
  2541                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2542                              <1> 	;
  2543                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2544                              <1> 	;
  2545 00005EDE 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2546 00005EE5 8A83[6F6E0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2547                              <1> 	; 13/01/2014
  2548 00005EEB EB02                <1> 	jmp	short ottyp
  2549                              <1> ocvt:
  2550 00005EED 2C0A                <1> 	sub	al, 10
  2551                              <1> ottyp:
  2552                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2553                              <1> 	; 16/11/2015
  2554                              <1> 	; 12/11/2015
  2555                              <1> 	; 18/05/2015 (32 bit modifications)
  2556                              <1> 	; 06/12/2013 - 13/07/2014
  2557 00005EEF 88C6                <1> 	mov	dh, al ; tty number
  2558 00005EF1 0FB6D8              <1> 	movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2559 00005EF4 D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2560                              <1> 	; 26/01/2014	
  2561 00005EF6 81C3[84700000]      <1> 	add 	ebx, ttyl
  2562 00005EFC 668B0B              <1> 	mov 	cx, [ebx]
  2563                              <1> 		   ; CL = lock value (0 or process number)
  2564                              <1> 		   ; CH = open count 
  2565 00005EFF 20C9                <1> 	and 	cl, cl
  2566                              <1> 	; 13/01/2014
  2567                              <1> 	;jz 	short otty_ret
  2568                              <1> 	; 05/12/2021
  2569 00005F01 743A                <1> 	jz 	short ottys_0
  2570                              <1> 	;
  2571                              <1> 	; 16/11/2015
  2572 00005F03 3A0D[89710000]      <1> 	cmp 	cl, [u.uno]
  2573 00005F09 745D                <1> 	je	short ottys_3
  2574                              <1> 	;
  2575 00005F0B 0FB6D9              <1> 	movzx 	ebx, cl ; the process which has locked the tty
  2576 00005F0E D0E3                <1> 	shl 	bl, 1
  2577 00005F10 668B83[0E6E0000]    <1> 	mov 	ax, [ebx+p.pid-2]
  2578                              <1> 	;movzx 	ebx, byte [u.uno]
  2579 00005F17 8A1D[89710000]      <1> 	mov	bl, [u.uno]
  2580 00005F1D D0E3                <1> 	shl 	bl, 1
  2581 00005F1F 663B83[2E6E0000]    <1> 	cmp 	ax, [ebx+p.ppid-2]
  2582 00005F26 7440                <1> 	je 	short ottys_3  ; 16/11/2015
  2583                              <1> 	;
  2584                              <1> 	; the tty is locked by another process
  2585                              <1> 	; except the parent process (p.ppid)
  2586                              <1>         ;
  2587 00005F28 C705[AC710000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2587 00005F30 0000                <1>
  2588                              <1> 			; permission denied ! error
  2589                              <1> otty_err: ; 13/01/2014
  2590 00005F32 08D2                <1> 	or 	dl, dl ; DL = 0 -> called by sysstty
  2591                              <1> 	;jnz	error
  2592                              <1> 	; 05/12/2021
  2593 00005F34 7405                <1> 	jz	short otty_stc_retn
  2594 00005F36 E98CDDFFFF          <1> 	jmp	error
  2595                              <1> otty_stc_retn:
  2596 00005F3B F9                  <1> 	stc
  2597 00005F3C C3                  <1> 	retn
  2598                              <1> ottys_0:
  2599                              <1> 	; 05/12/2021
  2600                              <1> otty_ret:
  2601                              <1> 	; 13/01/2014
  2602 00005F3D 80FE07              <1> 	cmp 	dh, 7
  2603 00005F40 761C                <1> 	jna	short ottys_2
  2604                              <1> 	; 16/11/2015
  2605                              <1> com_port_check:
  2606 00005F42 BE[A2700000]        <1> 	mov	esi, com1p
  2607 00005F47 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2608 00005F4A 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2609 00005F4C 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2610                              <1> ottys_1:
  2611                              <1> 	; 12/11/2015
  2612 00005F4D 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2613 00005F50 770C                <1> 	ja	short com_port_ready
  2614                              <1> 	;
  2615 00005F52 C705[AC710000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2615 00005F5A 0000                <1>
  2616                              <1> 			   ; device not ready ! error
  2617 00005F5C EBD4                <1> 	jmp	short otty_err	 
  2618                              <1> com_port_ready:
  2619                              <1> ottys_2:
  2620 00005F5E 08C9                <1> 	or	cl, cl  ; cl = lock/owner, ch = open count
  2621 00005F60 7506                <1> 	jnz	short ottys_3
  2622 00005F62 8A0D[89710000]      <1> 	mov	cl, [u.uno]
  2623                              <1> ottys_3:
  2624 00005F68 FEC5                <1> 	inc 	ch
  2625 00005F6A 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2626                              <1> 	; 06/12/2013
  2627 00005F6D FEC6                <1> 	inc	dh ; tty number + 1
  2628 00005F6F BB[6E710000]        <1> 	mov	ebx, u.ttyp
  2629                              <1> 	; 13/01/2014
  2630                              <1> 	;test	dl, 2 ; open for read sign
  2631                              <1> 	;jnz	short ottys_4
  2632                              <1> 	; 05/12/2021
  2633 00005F74 F6C202              <1> 	test	dl, 2
  2634 00005F77 7401                <1> 	jz	short ottys_4 ; open for read
  2635 00005F79 43                  <1> 	inc	ebx
  2636                              <1> ottys_4:
  2637                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2638 00005F7A 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2639                              <1> sret:
  2640 00005F7C 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2641 00005F7E 7401                <1> 	jz	short iclose_retn
  2642                              <1> 	;pop 	ax
  2643                              <1> 	; 05/12/2021
  2644 00005F80 58                  <1> 	pop	eax
  2645                              <1> iclose_retn:	
  2646 00005F81 C3                  <1> 	retn
  2647                              <1> 
  2648                              <1> 	;
  2649                              <1> 	; Original UNIX v1 'otty' routine:
  2650                              <1> 	;	
  2651                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2652                              <1>         ;                 / reader status reg
  2653                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2654                              <1>         ;                 / punch status reg
  2655                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2656                              <1>         ;                          / console tty buffer
  2657                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2658                              <1>         ;            / console tty
  2659                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2660                              <1>         ;             / buffer header
  2661                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2662                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2663                              <1>         ;                 / tty
  2664                              <1>         ;br     sret / ?
  2665                              <1> ;sret:
  2666                              <1> 		;clr *$ps / set processor priority to zero
  2667                              <1> ;	pop	ax
  2668                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2669                              <1> ;3:
  2670                              <1> ;	retn
  2671                              <1>         	;rts r0
  2672                              <1> 	
  2673                              <1> ;ocvt:	; < open tty >
  2674                              <1> 	; 13/01/2014
  2675                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2676                              <1> 	; 24/09/2013 consistency check -> ok
  2677                              <1> 	; 16/09/2013
  2678                              <1> 	; 03/09/2013
  2679                              <1> 	; 27/08/2013
  2680                              <1> 	; 16/08/2013
  2681                              <1> 	; 16/07/2013
  2682                              <1> 	; 27/05/2013
  2683                              <1> 	; 21/05/2013
  2684                              <1> 	;
  2685                              <1> 	; Retro UNIX 8086 v1 modification !
  2686                              <1> 	; 
  2687                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2688                              <1> 	;		(exactly different than this one)
  2689                              <1> 	;	was in 'u9.s' file.
  2690                              <1> 	;
  2691                              <1> 	; 16/07/2013
  2692                              <1> 	; Retro UNIX 8086 v1 modification:
  2693                              <1> 	;  If a tty is open for read or write by
  2694                              <1> 	;     a process (u.uno), only same process can open
  2695                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2696                              <1> 	;
  2697                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2698                              <1> 
  2699                              <1> 	; 16/09/2013
  2700                              <1> 	; sub 	al, 10
  2701                              <1> 	
  2702                              <1> 	; 06/12/2013
  2703                              <1> 	;cmp	al, 7
  2704                              <1>         ;jna	short ottyp
  2705                              <1> 	; 13/01/2014
  2706                              <1> 	;jmp	short ottyp
  2707                              <1> 
  2708                              <1> ;oppt: / open paper tape for reading or writing
  2709                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2710                              <1> ;        tstb   pptiflg / is file already open
  2711                              <1> ;        bne    2f / yes, branch
  2712                              <1> ;1:
  2713                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2714                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2715                              <1> ;               br .+4 / for paper tape input and place in free list
  2716                              <1> ;        br     1b
  2717                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2718                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2719                              <1> ;        br     sret
  2720                              <1> ;2:
  2721                              <1> ;        jmp    error / file already open
  2722                              <1> 
  2723                              <1> 	; 05/12/2021 - Retro UNIX 386 v2 fs compatibility modification
  2724                              <1> iclose:
  2725                              <1> 	; 05/12/2021 - Retro UNIX 386 v1.2
  2726                              <1> 	; 10/04/2021
  2727                              <1> 	; 08/04/2021
  2728                              <1> 	; 04/04/2021 - Retro UNIX 386 v2
  2729                              <1> 	; 19/05/2015
  2730                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2731                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2732                              <1> 	;
  2733                              <1> 	; close file whose i-number is in r1
  2734                              <1> 	; 
  2735                              <1> 	; INPUTS ->
  2736                              <1> 	;    r1 - inode number
  2737                              <1> 	; OUTPUTS ->
  2738                              <1> 	;    file's inode in core	
  2739                              <1> 	;    r1 - inode number (positive)
  2740                              <1> 	;
  2741                              <1> 	; ((AX = R1))
  2742                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2743                              <1> 	;        
  2744                              <1> ;;/ close file whose i-number is in r1
  2745                              <1> ;	mov	dl, 2 ; 12/01/2014
  2746                              <1> ;	test	ah, 80h ; Bit 15 of AX
  2747                              <1> ;		;tst r1 / test i-number
  2748                              <1> ;	;jnz	short iclose_2
  2749                              <1> ;		;blt 2f / if neg., branch
  2750                              <1> ;	jz	short iclose_0 ; 30/07/2013
  2751                              <1> ;	; 16/07/2013 
  2752                              <1> ;	neg	ax ; make it positive
  2753                              <1> ;	; 12/01/2014
  2754                              <1> ;	dec	dl ; dl = 1 (open for write)
  2755                              <1> ;iclose_0:
  2756                              <1> ;	cmp	ax, 40
  2757                              <1> ;		;cmp r1,$40. / is it a special file
  2758                              <1> ;       ja	short iclose_retn  ; 13/01/2014
  2759                              <1> ;		;bgt 3b / no, return
  2760                              <1> ;	; 12/01/2014
  2761                              <1> ;	; DL=2 -> special file was opened for reading
  2762                              <1> ;	; DL=1 -> special file was opened for writing
  2763                              <1> 
  2764                              <1> 	; 04/04/2021
  2765                              <1> 	; INPUT:
  2766                              <1> 	;	(e)ax = inode number
  2767                              <1> 	;	   dl = open mode
  2768                              <1> 	;		0 = control mode
  2769                              <1> 	;		1 = read
  2770                              <1> 	;		2 = write
  2771                              <1> 	; OUTPUT:
  2772                              <1> 	;	none
  2773                              <1> 	;	(if cf=1 -> eax = error code)
  2774                              <1> 	;	(if cf=0 -> ax = inode number)
  2775                              <1> 
  2776                              <1> 	; 10/04/2021
  2777                              <1>         ; Modified registers: ebx, ecx, edx, esi, edi, (ebp) 
  2778                              <1> 
  2779                              <1> 	; 05/12/2021
  2780                              <1> 	; 08/04/2021
  2781                              <1> 
  2782 00005F82 52                  <1> 	push	edx
  2783 00005F83 E85FF6FFFF          <1> 	call	iget
  2784 00005F88 5A                  <1> 	pop	edx 
  2785                              <1> 
  2786 00005F89 8A0D[D16D0000]      <1> 	mov	cl, [i.flgs+1]
  2787                              <1> 
  2788                              <1> 	; if i.flgs bit 15 is 1, it is regular file 
  2789                              <1> 	;test	byte [i.flgs+1], 80h ; is it a special file?
  2790 00005F8F F6C180              <1> 	test	cl, 80h ; is it a special file?
  2791 00005F92 75ED                <1> 	jnz	short iclose_retn ; no
  2792                              <1> 
  2793                              <1> 	;; inode flags - bit 13 must be 1 
  2794                              <1> 	;test	cl, 20h ; is it a valid device inode
  2795                              <1> 	;jnz	short iclose_retn ; no
  2796                              <1> 	
  2797                              <1> 	;push	ax
  2798                              <1> 	;	;mov r1,-(sp) / yes, save r1 on stack
  2799                              <1> 	;movzx	ebx, al
  2800                              <1> 	;shl	bx, 2
  2801                              <1> 	;	; asl r1
  2802                              <1> 	;add	ebx, iclose_1 - 4
  2803                              <1> 	;jmp	dword [ebx]
  2804                              <1> 	;	; jmp *1f-2(r1) / compute jump address and transfer
  2805                              <1> 
  2806                              <1> 	; 05/12/2021
  2807 00005F94 50                  <1> 	push	eax ; save inode number
  2808                              <1> 	; device file
  2809 00005F95 BB[AF5F0000]        <1> 	mov	ebx, iclose_1
  2810 00005F9A 83F808              <1> 	cmp	eax, 8	; /dev/tty inode number is 8
  2811 00005F9D 720E                <1> 	jb	short iclose_0
  2812 00005F9F 83F81A              <1> 	cmp	eax, 26	; /dev/tty9 (/dev/com2) inode number is 26
  2813 00005FA2 7709                <1> 	ja	short iclose_0
  2814                              <1> 	; convert v2 inode number to v1 device inode number
  2815 00005FA4 2C07                <1> 	sub	al, 7 ; 8 -> 1, 26 -> 19
  2816 00005FA6 89C1                <1> 	mov	ecx, eax
  2817 00005FA8 C0E102              <1> 	shl	cl, 2 ; * 4
  2818 00005FAB 01CB                <1> 	add	ebx, ecx
  2819                              <1> iclose_0:
  2820 00005FAD FF23                <1> 	jmp	dword [ebx]	
  2821                              <1> 		 ; jmp *1f-2(r1)
  2822                              <1> iclose_1: ; 1:
  2823 00005FAF [ED580000]          <1> 	dd	null ; 05/12/2021
  2824 00005FB3 [FF5F0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2825 00005FB7 [50600000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2826 00005FBB [50600000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2827 00005FBF [50600000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2828 00005FC3 [50600000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2829 00005FC7 [50600000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2830 00005FCB [50600000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2831 00005FCF [50600000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2832 00005FD3 [50600000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2833                              <1> 	;dd	error; lpr, AX = 9 (error!)
  2834                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2835 00005FD7 [0E600000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2836 00005FDB [0E600000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2837 00005FDF [0E600000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2838 00005FE3 [0E600000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2839 00005FE7 [0E600000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2840 00005FEB [0E600000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2841 00005FEF [0E600000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2842 00005FF3 [0E600000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2843 00005FF7 [0E600000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2844 00005FFB [0E600000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2845                              <1> 
  2846                              <1> 	; 1:
  2847                              <1> 	;        ctty   / tty
  2848                              <1> 	;        cppt   / ppt
  2849                              <1> 	;        sret   / mem
  2850                              <1> 	;        sret   / rf0
  2851                              <1> 	;        sret   / rk0
  2852                              <1> 	;        sret   / tap0
  2853                              <1> 	;        sret   / tap1
  2854                              <1> 	;        sret   / tap2
  2855                              <1> 	;        sret   / tap3
  2856                              <1> 	;        sret   / tap4
  2857                              <1> 	;        sret   / tap5
  2858                              <1> 	;        sret   / tap6
  2859                              <1> 	;        sret   / tap7
  2860                              <1> 	;        ccvt   / tty0
  2861                              <1> 	;        ccvt   / tty1
  2862                              <1> 	;        ccvt   / tty2
  2863                              <1> 	;        ccvt   / tty3
  2864                              <1> 	;        ccvt   / tty4
  2865                              <1> 	;        ccvt   / tty5
  2866                              <1> 	;        ccvt   / tty6
  2867                              <1> 	;        ccvt   / tty7
  2868                              <1> 	;        error / crd
  2869                              <1> 
  2870                              <1> ;iclose_2: ; 2: / negative i-number
  2871                              <1> 	;neg	ax
  2872                              <1> 		;neg r1 / make it positive
  2873                              <1> 	;cmp	ax, 40
  2874                              <1> 		;cmp r1,$40. / is it a special file?
  2875                              <1>         ;ja	short @b
  2876                              <1> 		;bgt    3b / no. return
  2877                              <1> 	;push	ax
  2878                              <1> 		;mov r1,-(sp)
  2879                              <1> 	;movzx	ebx, al
  2880                              <1> 	;shl	bx, 1
  2881                              <1> 		;asl r1 / yes. compute jump address and transfer
  2882                              <1> 	;add	ebx, iclose_3 - 2
  2883                              <1> 	;jmp	dword [ebx]
  2884                              <1> 		;jmp *1f-2(r1) / figure out 
  2885                              <1> ;iclose_3:
  2886                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2887                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2888                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2889                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2890                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2891                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2892                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2893                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2894                              <1> 	;;dd	sret ; lpr, AX = 9	
  2895                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2896                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2897                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2898                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2899                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2900                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2901                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2902                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2903                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2904                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2905                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2906                              <1> 	
  2907                              <1> 	;1:
  2908                              <1> 	;      	ctty   / tty
  2909                              <1> 	;       leadr  / ppt
  2910                              <1> 	;       sret   / mem
  2911                              <1> 	;       sret   / rf0
  2912                              <1> 	;       sret   / rk0
  2913                              <1> 	;       sret   / tap0
  2914                              <1> 	;       sret   / tap1
  2915                              <1> 	;       sret   / tap2
  2916                              <1> 	;       sret   / tap3
  2917                              <1> 	;       sret   / tap4
  2918                              <1> 	;       sret   / tap5
  2919                              <1> 	;       sret   / tap6
  2920                              <1> 	;       sret   / tap7
  2921                              <1> 	;       ccvt   / tty0
  2922                              <1> 	;       ccvt   / tty1
  2923                              <1> 	;       ccvt   / tty2
  2924                              <1> 	;       ccvt   / tty3
  2925                              <1> 	;       ccvt   / tty4
  2926                              <1> 	;       ccvt   / tty5
  2927                              <1> 	;       ccvt   / tty6
  2928                              <1> 	;       ccvt   / tty7
  2929                              <1> 	;/       ejec / lpr
  2930                              <1> 
  2931                              <1> ctty: ; / close console tty
  2932                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2933                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2934                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2935                              <1> 	;
  2936                              <1> 	; Retro UNIX 8086 v1 modification !
  2937                              <1> 	; (DL = 2 -> it is open for reading)
  2938                              <1> 	; (DL = 1 -> it is open for writing)
  2939                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2940                              <1> 	;
  2941                              <1> 	; 06/12/2013
  2942 00005FFF 0FB61D[89710000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2943 00006006 8A83[6F6E0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2944                              <1> 	; 13/01/2014
  2945 0000600C EB02                <1> 	jmp	short cttyp
  2946                              <1> ccvt:
  2947 0000600E 2C0A                <1> 	sub 	al, 10
  2948                              <1> cttyp:	
  2949                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2950                              <1> 	; 18/05/2015 (32 bit modifications)
  2951                              <1> 	; 16/08/2013 - 26/01/2014
  2952 00006010 0FB6D8              <1> 	movzx 	ebx, al ; tty number (0 to 9)
  2953 00006013 D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2954                              <1> 	; 26/01/2014
  2955 00006015 81C3[84700000]      <1> 	add 	ebx, ttyl
  2956 0000601B 88C6                <1> 	mov 	dh, al ; tty number
  2957 0000601D 668B03              <1> 	mov 	ax, [ebx]
  2958                              <1> 		   ; AL = lock value (0 or process number)
  2959                              <1> 		   ; AH = open count 
  2960 00006020 20E4                <1> 	and 	ah, ah
  2961 00006022 750F                <1> 	jnz	short ctty_ret
  2962 00006024 C705[AC710000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  2962 0000602C 0000                <1>
  2963                              <1> 			; device not open ! error
  2964                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  2965 0000602E E994DCFFFF          <1> 	jmp	error
  2966                              <1> 	; 26/01/2014
  2967                              <1> ctty_ret:
  2968 00006033 FECC                <1> 	dec 	ah ; decrease open count
  2969 00006035 7502                <1> 	jnz	short ctty_1
  2970 00006037 30C0                <1> 	xor	al, al ; unlock/free tty
  2971                              <1> ctty_1:
  2972 00006039 668903              <1> 	mov 	[ebx], ax ; close tty instance
  2973                              <1> 	;
  2974 0000603C BB[6E710000]        <1> 	mov	ebx, u.ttyp
  2975                              <1> 	;test	dl, 1 ; open for write sign
  2976                              <1> 	;jz	short ctty_2
  2977                              <1> 	; 05/12/2021
  2978 00006041 F6C202              <1> 	test	dl, 2 ; open for write sign
  2979 00006044 7401                <1> 	jz	short ctty_2	
  2980 00006046 43                  <1> 	inc	ebx
  2981                              <1> ctty_2:
  2982 00006047 FEC6                <1> 	inc	dh ; tty number + 1
  2983 00006049 3A33                <1> 	cmp	dh, [ebx]
  2984 0000604B 7503                <1> 	jne	short cret
  2985                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  2986 0000604D C60300              <1> 	mov	byte [ebx], 0
  2987                              <1> cret:
  2988 00006050 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2989 00006052 7401                <1> 	jz	short ctty_3
  2990                              <1> 	;pop	ax
  2991                              <1> 	; 05/12/2021
  2992 00006054 58                  <1> 	pop	eax
  2993                              <1> ctty_3:
  2994 00006055 C3                  <1> 	retn
  2995                              <1> 
  2996                              <1> ;ctty_err: ; 13/01/2014
  2997                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  2998                              <1> ;	jnz	error
  2999                              <1> ;	stc
  3000                              <1> ;	retn
  3001                              <1> 
  3002                              <1> 	; Original UNIX v1 'ctty' routine:
  3003                              <1> 	;	
  3004                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3005                              <1> 	;		;/ point r5 to the console tty buffer
  3006                              <1>         ;decb   (r5) / dec number of processes using console tty
  3007                              <1>         ;br     sret / return via sret
  3008                              <1> 
  3009                              <1> ;ccvt:	; < close tty >
  3010                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3011                              <1> 	;
  3012                              <1> 	; Retro UNIX 8086 v1 modification !
  3013                              <1> 	; 
  3014                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3015                              <1> 	;		(exactly different than this one)
  3016                              <1> 	;	was in 'u9.s' file.
  3017                              <1> 	;
  3018                              <1> 	; DL = 2 -> it is open for reading
  3019                              <1> 	; DL = 1 -> it is open for writing
  3020                              <1> 	;
  3021                              <1> 	; 17/09/2013
  3022                              <1> 	;sub 	al, 10
  3023                              <1> 	;cmp	al, 7
  3024                              <1> 	;jna	short cttyp
  3025                              <1> 	; 13/01/2014
  3026                              <1> 	;jmp	short cttyp
  3027                              <1> 
  3028                              <1> ;cppt: / close paper tape
  3029                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3030                              <1> ;1:
  3031                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3032                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3033                              <1> ;                          / and assign to free list
  3034                              <1> ;               br sret
  3035                              <1> ;        br     1b
  3036                              <1> 
  3037                              <1> ;ejec:	
  3038                              <1> ;	jmp	error
  3039                              <1> ;/ejec:
  3040                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3041                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3042                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3043                              <1> ;/       br     sret / return to caller via 'sret'
  2027                                  %include 'u8.s'      ; 11/06/2015
  2028                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2029                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2030                              <1> ; ****************************************************************************
  2031                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS8.INC
  2032                              <1> ; Last Modification: 24/12/2021
  2033                              <1> ; ----------------------------------------------------------------------------
  2034                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2035                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2036                              <1> ;
  2037                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2038                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2039                              <1> ; <Bell Laboratories (17/3/1972)>
  2040                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2041                              <1> ;
  2042                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2043                              <1> ;
  2044                              <1> ; ****************************************************************************
  2045                              <1> 
  2046                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2047                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2048                              <1> ;; Word 1, byte 0 = device id
  2049                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2050                              <1> ;;          bit 9 = write bit
  2051                              <1> ;;	    bit 10 = read bit	  
  2052                              <1> ;;	    bit 12 = waiting to write bit	
  2053                              <1> ;;	    bit 13 = waiting to read bit
  2054                              <1> ;;	    bit 15 = inhibit bit
  2055                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2056                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2057                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2058                              <1> ;;
  2059                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2060                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2061                              <1> ;;
  2062                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2063                              <1> ;; Word 1, Byte 0 = device id
  2064                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2065                              <1> ;;          bit 9 = write bit
  2066                              <1> ;;	    bit 10 = read bit	  
  2067                              <1> ;;	    bit 12 = waiting to write bit	
  2068                              <1> ;;	    bit 13 = waiting to read bit
  2069                              <1> ;;	    bit 15 = inhibit bit
  2070                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2071                              <1> ;;
  2072                              <1> ;; Original UNIX v1 ->
  2073                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2074                              <1> ;; Original UNIX v1 -> 
  2075                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2076                              <1> ;;
  2077                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2078                              <1> ;;
  2079                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2080                              <1> ;;          0 = fd0
  2081                              <1> ;;	    1 = fd1
  2082                              <1> ;;	    2 = hd0
  2083                              <1> ;;	    3 = hd1
  2084                              <1> ;;	    4 = hd2
  2085                              <1> ;;	    5 = hd3
  2086                              <1> 
  2087                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2088                              <1> 
  2089                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2090                              <1> 	; 26/04/2013
  2091                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2092                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2093                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2094                              <1> 
  2095                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2096                              <1> 	; 26/04/2013
  2097                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2098                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2099                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2100                              <1> 
  2101                              <1> bread: 
  2102                              <1> 	; 14/07/2015
  2103                              <1> 	; 10/07/2015
  2104                              <1> 	; 09/06/2015
  2105                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2106                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2107                              <1> 	;	
  2108                              <1> 	; / read a block from a block structured device
  2109                              <1> 	;
  2110                              <1> 	; INPUTS ->
  2111                              <1> 	;    [u.fopf] points to the block number
  2112                              <1> 	;    CX = maximum block number allowed on device
  2113                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2114                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2115                              <1> 	;    [u.count]	number of bytes to read in
  2116                              <1> 	; OUTPUTS ->
  2117                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2118                              <1> 	;    [u.fopf] points to next consecutive block to be read
  2119                              <1> 	;
  2120                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2121                              <1> 	;
  2122                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2123                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2124                              <1> 	;	is increased by 1. For example: If user/program request 
  2125                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2126                              <1> 	;  	the next block number just as 512 byte reading is done.
  2127                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2128                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2129                              <1> 	;       enough to keep byte position/offset of the disk), this
  2130                              <1> 	;	defect will not be corrected, user/program must request
  2131                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2132                              <1> 	;       for achieving correct result. In future version(s), 
  2133                              <1> 	;	this defect will be corrected by using different 
  2134                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2135                              <1> 
  2136                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2137                              <1> 			       ; / (only works on tape)
  2138                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2139                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2140                              <1> ;1:
  2141                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2142                              <1> 			    ; / maximum block # allowed on device
  2143                              <1> 		; jnb short @f
  2144                              <1> 		; bhis	1f / yes, 1f (error)
  2145                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2146                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2147                              <1> 		; mov (sp)+,r1 / return block # to r1
  2148                              <1> 		; inc r1 / bump block # to next consecutive block
  2149                              <1> 		; dec (sp) / "2-1-cold" on stack
  2150                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2151                              <1> ;1:
  2152                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2153                              <1> 	;push	ecx ; **
  2154                              <1> 	;26/04/2013
  2155                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2156 00006056 2C03                <1> 	sub	al, 3
  2157                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2158 00006058 A2[AB710000]        <1> 	mov	[u.brwdev], al
  2159                              <1> 	; 09/06/2015
  2160 0000605D 0FB6D8              <1> 	movzx	ebx, al
  2161 00006060 8B8B[5E6B0000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2162                              <1> bread_0:
  2163 00006066 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2164                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2165                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2166 00006067 8B1D[48710000]      <1> 	mov	ebx, [u.fofp]
  2167 0000606D 8B03                <1> 	mov	eax, [ebx]
  2168 0000606F C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2169                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2170                              <1> 			       ; / block #
  2171 00006072 39C8                <1> 	cmp	eax, ecx
  2172                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2173                              <1>        	                     ; / block number allowed
  2174                              <1> 	;jnb	error 	     ; 18/04/2013
  2175                              <1> 		; bhis error10 / yes, error
  2176 00006074 720F                <1> 	jb	short bread_1
  2177 00006076 C705[AC710000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2177 0000607E 0000                <1>
  2178 00006080 E942DCFFFF          <1> 	jmp	error
  2179                              <1> bread_1:
  2180                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2181                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2182                              <1> 	; eAX = Block number (zero based)
  2183                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2184                              <1> preread: ;; call preread
  2185 00006085 BF[AB710000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2186 0000608A E86B020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2187                              <1> 	;; jc 	error
  2188                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2189                              <1>         ; eAX = Block/Sector number (r1)
  2190                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2191                              <1> 	; 14/03/2013
  2192 0000608F 740A                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2193                              <1>        		; br 1f / branch if block already in a I/O buffer
  2194 00006091 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2195                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2196 00006096 E8B3010000          <1> 	call	poke
  2197                              <1>         	; jsr r0,poke / perform the read
  2198                              <1> 	;;jc	error ;2 0/07/2013
  2199                              <1> ; 1:
  2200                              <1>  		; clr *$ps / ps = 0
  2201                              <1>         	; rts r0
  2202                              <1> ;; return from preread
  2203                              <1> bread_2:
  2204 0000609B 66810B0040          <1> 	or	word [ebx], 4000h 
  2205                              <1> 		; bis $40000,(r5) 
  2206                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2207                              <1> bread_3: ; 1:
  2208 000060A0 66F7030024          <1> 	test	word [ebx], 2400h
  2209                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2210 000060A5 7407                <1> 	jz	short bread_4
  2211                              <1> 		; beq 1f / no
  2212                              <1> 		; cmp cdev,$1 / disk or drum?
  2213                              <1> 		; ble 2f / yes
  2214                              <1> 		; tstb uquant / is the time quantum = 0?
  2215                              <1> 		; bne 2f / no, 2f
  2216                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2217                              <1> 		; jsr r0,sleep; 31. 
  2218                              <1> 			; / put process to sleep in channel 31 (tape)
  2219                              <1> 		; mov (sp)+,r5 / restore r5
  2220                              <1> 		; br 1b / go back
  2221                              <1> ; 2: / drum or disk
  2222                              <1>         ;; mov     cx, [s.wait_]+2 ;; 29/07/2013
  2223 000060A7 E8F6F0FFFF          <1> 	call	idle
  2224                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2225 000060AC EBF2                <1> 	jmp	short bread_3
  2226                              <1>        		; br 1b
  2227                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2228 000060AE 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2229                              <1> 		; bic $40000,(r5) / clear bit 14
  2230                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2231 000060B3 83C308              <1> 	add	ebx, 8
  2232                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2233                              <1> 	; 09/06/2015
  2234 000060B6 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0
  2235 000060BE 7705                <1> 	ja	short bread_5
  2236 000060C0 E843F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2237                              <1> bread_5:
  2238                              <1> 	; eBX = system (I/O) buffer address
  2239 000060C5 E870000000          <1> 	call	dioreg
  2240                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2241                              <1> 	; esi =  start address of the transfer (in the buffer)
  2242                              <1> 	; edi =  [u.pbase], destination address in user's memory space
  2243                              <1> 	; ecx =  transfer count (in bytes)
  2244                              <1> 	;
  2245                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2246                              <1> ;   / of users data
  2247 000060CA F3A4                <1> 	rep	movsb
  2248                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2249                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2250                              <1>        		; bne 1b
  2251 000060CC 59                  <1> 	pop	ecx ; **
  2252 000060CD 833D[60710000]00    <1> 	cmp	dword [u.count], 0
  2253                              <1> 		; tst u.count / done
  2254 000060D4 7790                <1> 	ja	short bread_0 ; 09/06/2015
  2255                              <1>        		; beq 1f / yes, return
  2256                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2257                              <1>        		; br bread / read some more
  2258                              <1> ; 1:
  2259 000060D6 58                  <1> 	pop	eax ; ****
  2260                              <1>        		; mov (sp)+,r0
  2261 000060D7 C3                  <1>         retn		; 09/06/2015
  2262                              <1> 	;jmp     ret_ 
  2263                              <1> 		;jmp ret  / jump to routine that called readi
  2264                              <1> 
  2265                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2266                              <1> 	; 26/04/2013
  2267                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2268                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2269                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2270                              <1> 				
  2271                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2272                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2273                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2274                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2275                              <1> 
  2276                              <1> bwrite: 
  2277                              <1> 	; 14/07/2015
  2278                              <1> 	; 10/07/2015
  2279                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2280                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2281                              <1> 	;	
  2282                              <1> 	;; / write on block structured device
  2283                              <1> 	;
  2284                              <1> 	; INPUTS ->
  2285                              <1> 	;    [u.fopf] points to the block number
  2286                              <1> 	;    CX = maximum block number allowed on device
  2287                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2288                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2289                              <1> 	;    [u.count]	number of bytes to user desires to write
  2290                              <1> 	; OUTPUTS ->
  2291                              <1> 	;    [u.fopf] points to next consecutive block to be written into
  2292                              <1> 	;
  2293                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2294                              <1> 	;
  2295                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2296                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2297                              <1> 	;	is increased by 1. For example: If user/program request 
  2298                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2299                              <1> 	;  	the next block number just as 512 byte writing is done.
  2300                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2301                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2302                              <1> 	;       enough to keep byte position/offset of the disk), this
  2303                              <1> 	;	defect will not be corrected, user/program must request
  2304                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2305                              <1> 	;       for achieving correct result. In future version(s), 
  2306                              <1> 	;	this defect will be corrected by using different 
  2307                              <1> 	;       user (u) structure.  26/07/2013 - Erdogan Tan 	
  2308                              <1> 
  2309                              <1>        		; jsr r0,tstdeve / test the device for an error
  2310                              <1> 	;push	ecx ; **
  2311                              <1> 	;26/04/2013
  2312                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2313 000060D8 2C03                <1> 	sub	al, 3
  2314                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2315 000060DA A2[AB710000]        <1> 	mov	[u.brwdev], al
  2316                              <1> 	; 09/06/2015
  2317 000060DF 0FB6D8              <1> 	movzx	ebx, al
  2318 000060E2 8B8B[5E6B0000]      <1> 	mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2319                              <1> bwrite_0:
  2320 000060E8 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2321                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2322                              <1> 	; [u.fopf] points to byte position in disk, not sector/block !
  2323 000060E9 8B1D[48710000]      <1> 	mov	ebx, [u.fofp]
  2324 000060EF 8B03                <1> 	mov	eax, [ebx]       
  2325 000060F1 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2326                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2327 000060F4 39C8                <1> 	cmp	eax, ecx
  2328                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2329                              <1>        	                     ; / block number allowed
  2330                              <1> 	;jnb	error	     ; 18/04/2013
  2331                              <1> 		; bhis error10 / yes, error
  2332 000060F6 720F                <1>      	jb	short bwrite_1
  2333 000060F8 C705[AC710000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error	
  2333 00006100 0000                <1>
  2334 00006102 E9C0DBFFFF          <1> 	jmp	error
  2335                              <1> bwrite_1:
  2336                              <1> 	; inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2337                              <1> 		; inc *u.fofp / no, increment block number
  2338                              <1> 	; 09/06/2015 - 10/07/2015
  2339 00006107 66833D[A4710000]00  <1> 	cmp	word [u.pcount], 0
  2340 0000610F 7705                <1> 	ja	short bwrite_2
  2341 00006111 E8EEF8FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2342                              <1> bwrite_2:
  2343 00006116 BF[AB710000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2344 0000611B E8C4000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2345                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2346                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2347 00006120 E815000000          <1>         call	dioreg
  2348                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2349                              <1> 	; esi =  destination address (in the buffer)
  2350                              <1> 	; edi =  [u.pbase], start address of transfer in user's memory space
  2351                              <1> 	; ecx =  transfer count (in bytes)
  2352                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2353 00006125 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2354 00006127 F3A4                <1> 	rep	movsb
  2355                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2356                              <1>        		; dec r3 / area to the I/O buffer
  2357                              <1>        		; bne 1b
  2358 00006129 E8FE000000          <1> 	call	dskwr
  2359                              <1> 		; jsr r0,dskwr / write it out on the device
  2360 0000612E 59                  <1> 	pop	ecx ; **
  2361 0000612F 833D[60710000]00    <1>         cmp     dword [u.count], 0
  2362                              <1> 		; tst u.count / done
  2363 00006136 77B0                <1> 	ja	short bwrite_0 ; 09/06/2015
  2364                              <1> 		; beq 1f / yes, 1f
  2365                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2366                              <1>        		; br bwrite / go back and write next block
  2367                              <1> ; 1:
  2368 00006138 58                  <1> 	pop	eax ; ****
  2369                              <1>        		; mov (sp)+,r0
  2370 00006139 C3                  <1> 	retn		; 09/06/2015
  2371                              <1>         ;jmp     ret_ 
  2372                              <1> 		; jmp ret / return to routine that called writei
  2373                              <1> ;error10:
  2374                              <1> ;       jmp     error  ; / see 'error' routine
  2375                              <1> 
  2376                              <1> dioreg:
  2377                              <1> 	; 14/07/2015
  2378                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2379                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2380                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2381                              <1> 	;	
  2382                              <1> 	; bookkeeping on block transfers of data
  2383                              <1> 	;
  2384                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2385                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2386                              <1> 	; 10/07/2015
  2387                              <1> 	; * returns byte offset from beginning of current sector buffer
  2388                              <1> 	; (beginning of data) in ESI
  2389                              <1> 	;
  2390 0000613A 8B0D[60710000]      <1> 	mov	ecx, [u.count]
  2391                              <1> 		; mov u.count,r3 / move char count to r3
  2392 00006140 81F900020000        <1>        	cmp 	ecx, 512
  2393                              <1> 		; cmp r3,$512. / more than 512. char?
  2394 00006146 7605                <1> 	jna	short dioreg_0
  2395                              <1> 		; blos 1f / no, branch
  2396 00006148 B900020000          <1> 	mov	ecx, 512
  2397                              <1> 		; mov $512.,r3 / yes, just take 512.
  2398                              <1> dioreg_0:
  2399                              <1> 	; 09/06/2015
  2400 0000614D 663B0D[A4710000]    <1> 	cmp	cx, [u.pcount]
  2401 00006154 7607                <1> 	jna	short dioreg_1
  2402 00006156 668B0D[A4710000]    <1> 	mov	cx, [u.pcount]
  2403                              <1> dioreg_1:
  2404                              <1> ; 1:
  2405 0000615D 8B15[5C710000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2406                              <1> 	        ; mov u.base,r2 / put users base in r2
  2407 00006163 010D[64710000]      <1> 	add	[u.nread], ecx
  2408                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2409 00006169 290D[60710000]      <1> 	sub	[u.count], ecx
  2410                              <1> 		; sub r3,u.count / update count
  2411 0000616F 010D[5C710000]      <1> 	add	[u.base], ecx
  2412                              <1> 		; add r3,u.base / update base
  2413                              <1> 	; 10/07/2015
  2414                              <1> 	; Retro UNIX 386 v1 - modification !
  2415                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2416                              <1> 	; (It will point to next byte position instead of next block no.)
  2417 00006175 8B35[48710000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2418 0000617B 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2419 0000617D 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2420 0000617F 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2421 00006184 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2422 00006186 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2423                              <1> 	; 09/06/2015 - 10/07/2015
  2424 00006188 66290D[A4710000]    <1> 	sub	[u.pcount], cx
  2425 0000618F 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2426 00006195 8B3D[A0710000]      <1> 	mov	edi, [u.pbase]
  2427 0000619B 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2428 000061A1 01D7                <1> 	add	edi, edx
  2429 000061A3 893D[A0710000]      <1> 	mov	[u.pbase], edi
  2430 000061A9 010D[A0710000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2431 000061AF C3                  <1> 	retn
  2432                              <1> 		; rts r0 / return
  2433                              <1> 
  2434                              <1> dskrd:
  2435                              <1> 	; 18/08/2015
  2436                              <1> 	; 02/07/2015
  2437                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2438                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2439                              <1> 	;
  2440                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2441                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2442                              <1> 	; (number specified in r1) in the acquired buffer.)
  2443                              <1> 	; If the device is busy at the time dskrd is called,	
  2444                              <1> 	; dskrd calls idle.
  2445                              <1> 	; 
  2446                              <1> 	; INPUTS ->
  2447                              <1> 	;    r1 - block number
  2448                              <1> 	;    cdev - current device number 
  2449                              <1> 	; OUTPUTS ->
  2450                              <1> 	;    r5 - points to first data word in I/O buffer
  2451                              <1> 	;
  2452                              <1> 	; ((AX = R1)) input/output
  2453                              <1> 	; ((BX = R5)) output 
  2454                              <1> 	;
  2455                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2456                              <1> 	;
  2457 000061B0 E837010000          <1> 	call 	bufaloc
  2458                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2459                              <1> 			       ; / get a free I/O buffer
  2460                              <1> 	;;jc	error ; 20/07/2013
  2461 000061B5 741B                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2462                              <1>        		; br 1f / branch if block already in a I/O buffer
  2463                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2464 000061B7 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2465                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2466                              <1> 		               ; / I/O queue entry for buffer
  2467 000061BC E88D000000          <1> 	call	poke
  2468                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2469                              <1> 			    ; /	bit 10=1 says read
  2470                              <1> 	; 09/06/2015
  2471 000061C1 730F                <1> 	jnc	short dskrd_1
  2472                              <1> 	;
  2473 000061C3 C705[AC710000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2473 000061CB 0000                <1>
  2474 000061CD E9F5DAFFFF          <1> 	jmp	error
  2475                              <1> dskrd_1: ; 1:
  2476                              <1>        		;clr *$ps
  2477 000061D2 66F7030024          <1>        	test	word [ebx], 2400h
  2478                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2479                              <1> 				; / jump to idle
  2480 000061D7 7407                <1>        	jz	short dskrd_2
  2481                              <1> 		; beq 1f
  2482                              <1>         ;;mov   ecx, [s.wait_]
  2483 000061D9 E8C4EFFFFF          <1>        	call	idle
  2484                              <1> 		; jsr r0,idle; s.wait+2
  2485 000061DE EBF2                <1> 	jmp 	short dskrd_1
  2486                              <1>        		; br 1b
  2487                              <1> dskrd_2: ; 1:
  2488 000061E0 83C308              <1>         add	ebx, 8
  2489                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2490                              <1> 			  ; / just read in
  2491 000061E3 C3                  <1>        	retn
  2492                              <1> 		; rts r0
  2493                              <1> 
  2494                              <1> bwslot:
  2495                              <1> 	; 10/07/2015
  2496                              <1> 	;	If the block/sector is not placed in a buffer
  2497                              <1> 	;	before 'wslot', it must be read before
  2498                              <1> 	;	it is written! (Otherwise transfer counts less
  2499                              <1> 	;	than 512 bytes will be able to destroy existing 
  2500                              <1> 	;	data on disk.)
  2501                              <1> 	;
  2502                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2503                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2504                              <1> 	; Retro UNIX 8086 v1 modification !
  2505                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2506                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2507                              <1> 	;	-> eAX = block number
  2508                              <1> 	;
  2509 000061E4 E811010000          <1> 	call	bufaloc_0
  2510 000061E9 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2511                              <1> bwslot_0:
  2512                              <1> 	; 10/07/2015
  2513 000061EB 8B35[48710000]      <1> 	mov	esi, [u.fofp]
  2514 000061F1 8B06                <1> 	mov	eax, [esi]
  2515 000061F3 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2516 000061F8 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2517                              <1> 		       ; recent disk data must be placed in the buffer
  2518 000061FA 813D[60710000]0002- <1> 	cmp	dword [u.count], 512
  2518 00006202 0000                <1>
  2519 00006204 730F                <1> 	jnb	short wslot_0	
  2520                              <1> bwslot_1:
  2521 00006206 E8ACFFFFFF          <1> 	call	dskrd_0
  2522 0000620B 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again	
  2523 0000620E EB05                <1> 	jmp 	short wslot_0
  2524                              <1> 
  2525                              <1> wslot:
  2526                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2527                              <1> 	; 		(32 bit modifications)
  2528                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2529                              <1> 	;
  2530                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2531                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2532                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2533                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2534                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2535                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2536                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2537                              <1> 	;
  2538                              <1> 	; INPUTS ->
  2539                              <1>  	;    r1 - block number
  2540                              <1> 	;    cdev - current (block/disk) device number
  2541                              <1>  	;
  2542                              <1> 	; OUTPUTS ->
  2543                              <1> 	;    bufp - bits 9 and 15 are set, 
  2544                              <1> 	;           the remainder of the word left unchanged
  2545                              <1> 	;    r5 - points to first data word in I/O buffer
  2546                              <1> 	;
  2547                              <1> 	; ((AX = R1)) input/output
  2548                              <1> 	; ((BX = R5)) output 
  2549                              <1> 	;
  2550                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2551                              <1> 
  2552 00006210 E8D7000000          <1> 	call	bufaloc
  2553                              <1> 	; 10/07/2015
  2554                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2555                              <1>         	; br 1f / word in buffer in r5
  2556                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2557                              <1>         ; eAX = Block/Sector number (r1)
  2558                              <1> wslot_0: ;1:
  2559 00006215 66F7030024          <1>      	test	word [ebx], 2400h
  2560                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2561                              <1> 				; / of I/O queue entry
  2562 0000621A 7407                <1> 	jz	short wslot_1
  2563                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2564                              <1> 		     ; / or not waiting to read)
  2565                              <1> 
  2566                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2567 0000621C E881EFFFFF          <1> 	call	idle
  2568                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2569                              <1>        	                     ; / idle
  2570 00006221 EBF2                <1> 	jmp	short wslot_0
  2571                              <1> 		; br 1b / till finished
  2572                              <1> wslot_1: ;1:
  2573 00006223 66810B0082          <1>         or      word [ebx], 8200h
  2574                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2575                              <1>                             	 ; / (write, inhibit bits)
  2576                              <1>        		; clr     *$ps / clear processor status
  2577 00006228 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2578                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2579                              <1> 			  ; / for this block
  2580 0000622B C3                  <1>        	retn
  2581                              <1> 		; rts r0
  2582                              <1> dskwr:
  2583                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2584                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2585                              <1> 	;
  2586                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2587                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2588                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2589                              <1> 	; previously has supplied all the information required in the
  2590                              <1> 	; I/O queue entry.
  2591                              <1> 	;
  2592                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2593                              <1> 	;
  2594                              <1> 	;
  2595 0000622C 8B1D[F0700000]      <1> 	mov	ebx, [bufp]
  2596 00006232 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2597                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2598                              <1>                                   ; / bottom of queue
  2599 00006237 E812000000          <1> 	call	poke
  2600                              <1> 	; 09/06/2015
  2601 0000623C 730F                <1> 	jnc	short dskwr_1
  2602 0000623E C705[AC710000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2602 00006246 0000                <1>
  2603 00006248 E97ADAFFFF          <1> 	jmp	error
  2604                              <1> dskwr_1:
  2605 0000624D C3                  <1> 	retn
  2606                              <1> 
  2607                              <1> 
  2608                              <1> ;ppoke:
  2609                              <1>        		; mov $340,*$ps
  2610                              <1>        		; jsr r0,poke
  2611                              <1>        		; clr *$ps
  2612                              <1> 		; rts r0
  2613                              <1> poke:
  2614                              <1> 	; 29/11/2021 (32 bit reg push-pop)
  2615                              <1> 	; 24/10/2015
  2616                              <1> 	; 20/08/2015
  2617                              <1> 	; 18/08/2015
  2618                              <1> 	; 02/07/2015
  2619                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2620                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2621                              <1> 	;
  2622                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2623                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2624                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2625                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2626                              <1> 	;
  2627                              <1> 	; Basic I/O functions for all block structured devices
  2628                              <1> 	;
  2629                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2630                              <1> 	;
  2631                              <1> 	; 20/07/2013 modifications
  2632                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2633                              <1> 	; INPUTS -> 
  2634                              <1> 	;        (EBX = buffer header address)
  2635                              <1> 	; OUTPUTS ->
  2636                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2637                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2638                              <1> 	;		(drive not ready or r/w error!)
  2639                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2640                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2641                              <1> 	;        (also it indicates invalid buffer data)
  2642                              <1> 	;
  2643 0000624E 53                  <1> 	push	ebx
  2644                              <1>        		; mov r1,-(sp)
  2645                              <1>        		; mov r2,-(sp)
  2646                              <1>        		; mov r3,-(sp)
  2647 0000624F 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2648                              <1> 	;
  2649                              <1> 	; 09/06/2015
  2650                              <1> 	; (permit read/write after a disk R/W error)
  2651 00006250 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2652 00006252 B001                <1> 	mov	al, 1
  2653 00006254 D2E0                <1> 	shl	al, cl
  2654 00006256 8405[18710000]      <1> 	test 	al, [active] ; busy ? (error)
  2655 0000625C 7408                <1> 	jz	short poke_0
  2656 0000625E F6D0                <1> 	not	al
  2657 00006260 2005[18710000]      <1> 	and	[active], al ; reset busy bit for this device only
  2658                              <1> poke_0:
  2659 00006266 BE[10710000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2660                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2661                              <1> 					 ; / I/O queue pointer
  2662                              <1> poke_1: ; 1:
  2663 0000626B 83EE04              <1>         sub	esi, 4
  2664 0000626E 8B1E                <1> 	mov	ebx, [esi]
  2665                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2666 00006270 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2667 00006273 F6C406              <1>        	test	ah, 06h
  2668                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2669                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2670                              <1> 			       ; / queue entry
  2671 00006276 745C                <1>         jz      short poke_5
  2672                              <1> 		; beq 2f / branch to 2f if both are clear
  2673                              <1> 	; 31/07/2013
  2674                              <1> 	;test	ah, 0B0h ; (*)
  2675                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2676                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2677                              <1>         ;jnz     short poke_5 ; 31/07/2013 (*)
  2678                              <1> 		; bne 2f / branch if any are set
  2679                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2680                              <1>     		; movb (r1),r3 / get device id
  2681 00006278 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2682                              <1> 	;mov	edi, ecx ; 26/04/2013
  2683 0000627B 31C0                <1> 	xor 	eax, eax ; 0
  2684                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2685                              <1> 		; tstb deverr(r3) / test for errors on this device
  2686                              <1>        	;jna	short poke_2 
  2687                              <1> 		; beq 3f / branch if no errors
  2688                              <1> 	; 02/07/2015
  2689                              <1> 	;dec	eax
  2690                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2691                              <1>        		; mov $-1,2(r1) / destroy associativity
  2692                              <1> 	;shr	eax, 24
  2693                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2694                              <1> 		; clrb 1(r1) / do not do I/O
  2695                              <1> 	;jmp     short poke_5
  2696                              <1>         ;       ; br 2f
  2697                              <1>                 ; rts r0
  2698                              <1> poke_2: ; 3:
  2699                              <1> 	; 02/07/2015
  2700 0000627D FEC1                <1> 	inc	cl ; 0FFh -> 0
  2701 0000627F 7453                <1> 	jz	short poke_5
  2702 00006281 FEC0                <1> 	inc	al ; mov ax, 1
  2703 00006283 FEC9                <1> 	dec	cl
  2704 00006285 7402                <1> 	jz	short poke_3
  2705                              <1> 	; 26/04/2013 Modification
  2706                              <1> 	;inc	al ; mov ax, 1
  2707                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2708                              <1> 	;jz	short poke_3 ; cl = 0
  2709 00006287 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2710                              <1> poke_3:
  2711                              <1> 	;test	[active], ax
  2712 00006289 8405[18710000]      <1> 	test	[active], al
  2713                              <1> 		; bit $2,active / test disk busy bit
  2714 0000628F 7543                <1> 	jnz     short poke_5
  2715                              <1> 		; bne 2f / branch if bit is set
  2716                              <1> 	;or	[active], ax
  2717 00006291 0805[18710000]      <1> 	or	[active], al
  2718                              <1> 		; bis $2,active / set disk busy bit
  2719 00006297 50                  <1> 	push	eax ; 29/11/2021
  2720 00006298 E8D3000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2721                              <1> 	;mov    [edi+drv.error], ah
  2722 0000629D 58                  <1> 	pop	eax
  2723 0000629E 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2724                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2725                              <1> 	;jna	short poke_4
  2726                              <1> 		; tstb deverr(r3) / test for errors on this device
  2727                              <1>        		; beq 3f / branch if no errors
  2728                              <1> 	; 02/07/2015 (32 bit modification)
  2729                              <1> 	; 20/07/2013
  2730 000062A0 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2731                              <1>        		; mov $-1,2(r1) / destroy associativity
  2732 000062A7 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2733                              <1> 		; clrb 1(r1) / do not do I/O
  2734 000062AC EB26                <1> 	jmp     short poke_5
  2735                              <1> poke_4:	; 20/07/2013
  2736                              <1> 	; 17/07/2013
  2737 000062AE F6D0                <1> 	not 	al 
  2738 000062B0 2005[18710000]      <1> 	and	[active], al ; reset, not busy
  2739                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2740                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2741 000062B6 668B03              <1> 	mov	ax, [ebx]
  2742                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2743 000062B9 66250006            <1>         and	ax, 600h
  2744                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2745 000062BD 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2746                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2747 000062C2 C0E403              <1> 	shl	ah, 3
  2748                              <1>        		; rol r3
  2749                              <1>                 ; rol r3
  2750                              <1>                 ; rol r3	
  2751 000062C5 660903              <1> 	or	[ebx], ax
  2752                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2753                              <1> 			   ; bits 12 and 13
  2754 000062C8 E8D5EEFFFF          <1> 	call	idle ; 18/01/2014
  2755                              <1> 	;; sti
  2756                              <1> 	;hlt 	; wait for a hardware interrupt
  2757                              <1> 	;; cli
  2758                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2759                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2760                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2761                              <1> 	; method, this procedure will wait for a time according to
  2762                              <1> 	; multi tasking and time sharing concept.
  2763                              <1> 	;
  2764                              <1> 	; 24/10/2015
  2765                              <1> 	;not	ax 
  2766 000062CD 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2767 000062D1 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2768                              <1> poke_5: ;2:
  2769 000062D4 81FE[F0700000]      <1>         cmp     esi, bufp
  2770                              <1> 		; cmp r2,$bufp / test to see if entire I/O queue 
  2771                              <1>                             ; / has been scanned
  2772 000062DA 778F                <1> 	ja      short poke_1
  2773                              <1> 		; bhi 1b
  2774                              <1> 	; 24/03/2013
  2775                              <1>        		; mov (sp)+,r3
  2776                              <1>        		; mov (sp)+,r2
  2777                              <1>        		; mov (sp)+,r1
  2778 000062DC 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2779 000062DD 5B                  <1> 	pop 	ebx
  2780                              <1> 	; 02/07/2015 (32 bit modification)
  2781                              <1> 	; 20/07/2013
  2782                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2783 000062DE 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2784                              <1> 	;	
  2785                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2786                              <1> 	; or written succesfully; even if an error occurs while
  2787                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2788                              <1> 	;
  2789                              <1> 	; 09/06/2015
  2790 000062E1 F5                  <1> 	cmc
  2791 000062E2 C3                  <1> 	retn
  2792                              <1>                 ; rts r0
  2793                              <1> 
  2794                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatibility code
  2795                              <1> get_system_time:
  2796                              <1> 	; 27/10/2021
  2797                              <1> 	; 21/02/2020 - Retro UNIX 386 v2
  2798                              <1> 	; get system time
  2799                              <1> 	;  (from recent value which is saved in RTC interrupt)
  2800                              <1> 	; Input:
  2801                              <1> 	; 	none
  2802                              <1> 	; Return:
  2803                              <1> 	;   	eax = system time in unix epoch format 
  2804                              <1> 	;
  2805                              <1> 	; Modified registers: eax, ecx, edx
  2806                              <1> 	
  2807                              <1> 	; 27/11/2021
  2808 000062E3 53                  <1> 	push	ebx
  2809 000062E4 E807D5FFFF          <1> 	call	epoch
  2810 000062E9 5B                  <1> 	pop	ebx
  2811 000062EA C3                  <1> 	retn
  2812                              <1> 
  2813                              <1> get_serial_number:
  2814                              <1> 	; temporary - 21/02/2020
  2815                              <1> 	; 26/04/2020 (esi)
  2816                              <1> 	; 25/04/2020
  2817                              <1> 	; (Possible) Modified registers: eax, ecx, edx
  2818                              <1> 	; (edi, ebx & esi registers must be preserved)
  2819                              <1> 	; Return:
  2820                              <1> 	; eax = 32 bit serial number  
  2821                              <1> 	; (edx = high 32 bit of 64 bit serial number)
  2822                              <1> 	; -64 bit serial numbers will not be used in RUNIX 386 v2-
  2823 000062EB C3                  <1> 	retn
  2824                              <1> 
  2825                              <1> bufaloc:
  2826                              <1> 	; 20/08/2015
  2827                              <1> 	; 19/08/2015
  2828                              <1> 	; 02/07/2015
  2829                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2830                              <1> 	;	     (32 bit modifications)	
  2831                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2832                              <1> 	;
  2833                              <1> 	; bufaloc - Block device I/O buffer allocation
  2834                              <1> 	; 
  2835                              <1> 	; INPUTS ->
  2836                              <1> 	;    r1 - block number
  2837                              <1> 	;    cdev - current (block/disk) device number
  2838                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2839                              <1> 	; OUTPUTS ->
  2840                              <1> 	;    r5 - pointer to buffer allocated
  2841                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2842                              <1> 	;
  2843                              <1> 	; ((AX = R1)) input/output
  2844                              <1> 	; ((BX = R5)) output
  2845                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2846                              <1> 	;    zf=1 -> block already in a I/O buffer
  2847                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2848                              <1> 	;    ((DL = Device ID))
  2849                              <1> 	;    (((DH = 0 or 1)))
  2850                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2851                              <1> 	;    ((CX and DH will not be used after return)))
  2852                              <1> 
  2853                              <1> 	;;push 	esi ; ***
  2854                              <1> 		; mov r2,-(sp) / save r2 on stack
  2855                              <1>        		; mov $340,*$ps / set processor priority to 7
  2856                              <1> 	; 20/07/2013
  2857                              <1> 	; 26/04/2013
  2858 000062EC 0FB61D[15710000]    <1> 	movzx	ebx, byte [cdev] ; 0 or 1
  2859 000062F3 BF[16710000]        <1> 	mov	edi, rdev  ; offset mdev = offset rdev + 1
  2860 000062F8 01DF                <1> 	add	edi, ebx
  2861                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2862                              <1> 			;; eDI points to device id.
  2863 000062FA 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2864                              <1> 	; 11/06/2021
  2865 000062FD 80BB[7A6B0000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2866 00006304 720F                <1> 	jb	short bufaloc_9
  2867 00006306 C705[AC710000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2867 0000630E 0000                <1>
  2868 00006310 E9B2D9FFFF          <1> 	jmp	error
  2869                              <1> bufaloc_9:
  2870 00006315 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2871                              <1> bufaloc_10: ; 02/07/2015
  2872 00006317 31ED                <1> 	xor 	ebp, ebp ; 0
  2873 00006319 55                  <1> 	push	ebp ; 0
  2874 0000631A 89E5                <1>         mov     ebp, esp	
  2875                              <1> 	;
  2876                              <1> bufaloc_1: ;1:
  2877                              <1> 		; clr -(sp) / vacant buffer
  2878 0000631C BE[F0700000]        <1>         mov 	esi, bufp
  2879                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2880                              <1> 			     ; / entrys in buffer area
  2881                              <1> bufaloc_2: ;2:
  2882 00006321 8B1E                <1> 	mov	ebx, [esi]
  2883                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  2884                              <1> 			    ; queue entry into r5
  2885 00006323 66F70300F6          <1> 	test	word [ebx], 0F600h
  2886                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  2887 00006328 7503                <1>         jnz	short bufaloc_3
  2888                              <1> 		; bne 3f / branch when 
  2889                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  2890                              <1>                        ; / (i.e., buffer busy)
  2891 0000632A 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  2892                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  2893                              <1> 			; / found points to word 2 of I/O queue entry)
  2894                              <1> bufaloc_3: ;3:
  2895                              <1> 	;mov	dl, [edi] ; 26/04/2013
  2896                              <1> 	;
  2897 0000632D 3813                <1> 	cmp	[ebx], dl	
  2898                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  2899                              <1> 			       ; / as current device
  2900 0000632F 7508                <1> 	jne	short bufaloc_4
  2901                              <1>        		; bne 3f
  2902 00006331 394304              <1> 	cmp	[ebx+4], eax
  2903                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  2904                              <1> 			     ; / same as current block number
  2905 00006334 7503                <1>        	jne	short bufaloc_4
  2906                              <1> 		; bne 3f
  2907                              <1> 	;add	esp, 4
  2908 00006336 59                  <1> 	pop	ecx
  2909                              <1>        		; tst (sp)+ / bump stack pointer
  2910 00006337 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  2911                              <1> 				; jump to bufaloc_6 in original Unix v1
  2912                              <1>        		; br 1f / use this buffer
  2913                              <1> bufaloc_4: ;3:
  2914 00006339 83C604              <1> 	add	esi, 4 ; 20/08/2015
  2915                              <1> 	;
  2916 0000633C 81FE[08710000]      <1> 	cmp	esi, bufp + (nbuf*4)
  2917                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  2918 00006342 72DD                <1> 	jb	short bufaloc_2
  2919                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  2920                              <1>                        ; / buffers not checked)
  2921 00006344 5E                  <1>         pop	esi
  2922                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  2923                              <1> 			     ; / to last free block
  2924 00006345 09F6                <1>        	or	esi, esi 
  2925 00006347 7507                <1> 	jnz	short bufaloc_5
  2926                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  2927                              <1> 	        ; / if a free buffer is found branch to 2f
  2928                              <1>         ;; mov  ecx, [s.wait_]
  2929 00006349 E854EEFFFF          <1> 	call	idle
  2930                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  2931 0000634E EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  2932                              <1>        		; br 1b
  2933                              <1> bufaloc_5: ;2:
  2934                              <1> 		; tst (r0)+ / skip if warmed over buffer
  2935 00006350 FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  2936                              <1> bufaloc_6: ;1:
  2937 00006352 8B1E                <1>         mov    	ebx, [esi] 
  2938                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  2939                              <1> 			     ; / entry in r5
  2940                              <1> 	;; 26/04/2013
  2941                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  2942 00006354 8813                <1> 	mov 	[ebx], dl
  2943                              <1> 		; movb cdev,(r5) / put current device number 
  2944                              <1> 				 ; / in I/O queue entry
  2945 00006356 894304              <1> 	mov 	[ebx+4], eax
  2946                              <1> 		; mov r1,2(r5) / move block number into word 2 
  2947                              <1> 			     ; / of I/O queue entry
  2948                              <1> bufaloc_7: ;1:
  2949 00006359 81FE[F0700000]      <1>         cmp	esi, bufp
  2950                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  2951                              <1> 			     ; / and put latest assigned
  2952 0000635F 760A                <1> 	jna	short bufaloc_8	
  2953                              <1>        		; blos 1f / buffer on the top 
  2954                              <1> 			; / (this makes if the lowest priority)
  2955 00006361 83EE04              <1> 	sub	esi, 4
  2956 00006364 8B0E                <1> 	mov	ecx, [esi]
  2957 00006366 894E04              <1> 	mov	[esi+4], ecx
  2958                              <1> 		; mov -(r2),2(r2) / job for a particular device
  2959 00006369 EBEE                <1> 	jmp 	short bufaloc_7        
  2960                              <1> 		; br 1b
  2961                              <1> bufaloc_8: ;1:
  2962 0000636B 891E                <1>         mov	[esi], ebx
  2963                              <1> 		; mov r5,(r2)
  2964                              <1> 	;;pop	esi ; ***
  2965                              <1>        		; mov (sp)+,r2 / restore r2
  2966 0000636D 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  2967                              <1> 		; Retro UNIX 8086 v1 modification
  2968                              <1> 		; zf=1 --> block already is in an I/O buffer
  2969                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  2970 0000636F C3                  <1> 	retn
  2971                              <1> 		; rts r0
  2972                              <1> 
  2973                              <1> diskio:
  2974                              <1> 	; 28/11/2021
  2975                              <1> 	; 10/07/2015
  2976                              <1> 	; 02/07/2015
  2977                              <1> 	; 16/06/2015
  2978                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2979                              <1> 	;	     (80386 protected mode modifications)	
  2980                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2981                              <1> 	;
  2982                              <1> 	; Retro UNIX 8086 v1 feature only !
  2983                              <1> 	;
  2984                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  2985                              <1> 	; 04/07/2009 - 20/07/2011
  2986                              <1> 	;
  2987                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  2988                              <1> 	;
  2989                              <1>         ; INPUTS ->
  2990                              <1> 	; 	   ebx = System I/O Buffer header address
  2991                              <1> 	;
  2992                              <1>         ; OUTPUTS -> cf=0 --> done 
  2993                              <1> 	; 	     cf=1 ---> error code in AH
  2994                              <1> 	;
  2995                              <1> 	; (Modified registers: eax, ecx, edx)
  2996                              <1> 	
  2997                              <1> ;rw_disk_sector:
  2998                              <1> 	; 28/11/2021
  2999                              <1> 	; 10/07/2015
  3000                              <1> 	; 02/07/2015
  3001                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3002                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3003                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3004                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3005                              <1> 	;
  3006                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3007 00006370 B602                <1> 	mov	dh, 2
  3008                              <1> 	;mov	ax, [ebx]
  3009                              <1> 	; 28/11/2021
  3010 00006372 8B03                <1> 	mov	eax, [ebx]
  3011                              <1> 	;
  3012 00006374 56                  <1> 	push	esi ; ****
  3013 00006375 53                  <1> 	push	ebx ; ***
  3014                              <1> 	;
  3015 00006376 0FB6C8              <1> 	movzx	ecx, al
  3016                              <1> 	; 28/11/2021
  3017                              <1> 	;mov	ecx, eax
  3018 00006379 89CE                <1> 	mov	esi, ecx
  3019                              <1> 	;
  3020 0000637B 38F1                <1> 	cmp	cl, dh ; 2
  3021 0000637D 7202                <1> 	jb	short rwdsk0
  3022 0000637F 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3023                              <1> rwdsk0:
  3024 00006381 A2[2B6B0000]        <1> 	mov	[drv], al
  3025 00006386 81C6[7A6B0000]      <1> 	add	esi, drv.status
  3026                              <1> 	; 11/06/2015
  3027 0000638C 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3028 0000638F 720F                <1> 	jb      short rwdsk1
  3029                              <1> 	; 'drive not ready' error
  3030 00006391 C705[AC710000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  3030 00006399 0000                <1>
  3031 0000639B E927D9FFFF          <1> 	jmp	error
  3032                              <1> rwdsk1:
  3033 000063A0 F6C402              <1> 	test	ah, 2
  3034                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3035                              <1> 			 ; write bit
  3036 000063A3 7402                <1> 	jz	short rwdsk2
  3037                              <1> 	;test	ah, 4
  3038                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3039                              <1> 	;		 ; read bit
  3040                              <1> 	;jz	short diskio_ret
  3041 000063A5 FEC6                <1> 	inc	dh ; 03h = write
  3042                              <1> rwdsk2:
  3043 000063A7 88C2                <1> 	mov	dl, al
  3044 000063A9 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3045 000063AC 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3046 000063AE C0E102              <1> 	shl	cl, 2
  3047 000063B1 81C1[5E6B0000]      <1> 	add	ecx, drv.size ; disk size
  3048 000063B7 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3049 000063B9 720F                <1> 	jb      short rwdsk3
  3050                              <1>  	; 'out of volume' error
  3051 000063BB C705[AC710000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE 	
  3051 000063C3 0000                <1>
  3052 000063C5 E9FDD8FFFF          <1> 	jmp	error
  3053                              <1> rwdsk3:
  3054                              <1> 	; 11/06/2015
  3055 000063CA 83C304              <1> 	add	ebx, 4 ; buffer address
  3056 000063CD C605[0B720000]04    <1> 	mov	byte [retry_count], 4
  3057 000063D4 F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3058 000063D7 7432                <1>         jz      short rwdsk_chs
  3059                              <1> rwdsk_lba:
  3060                              <1> 	; LBA read/write (with private LBA function) 
  3061                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3062 000063D9 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3063 000063DC 89C1                <1> 	mov	ecx, eax ; sector number
  3064                              <1> 	; ebx = buffer (data) address
  3065                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3066                              <1> rwdsk_lba_retry:
  3067                              <1> 	;mov	dl, [drv]
  3068                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3069 000063DE B419                <1> 	mov	ah, 1Ch - 03h ; LBA write function number - 3
  3070 000063E0 00F4                <1> 	add	ah, dh		
  3071 000063E2 B001                <1> 	mov	al, 1
  3072                              <1> 	;int	13h
  3073 000063E4 E86DC3FFFF          <1> 	call	int13h
  3074 000063E9 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3075 000063EB 730E                <1> 	jnc	short rwdsk_lba_ok
  3076 000063ED 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3077 000063F0 7408                <1>         je      short rwdsk_lba_fails
  3078 000063F2 FE0D[0B720000]      <1> 	dec	byte [retry_count]
  3079 000063F8 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3080                              <1> rwdsk_lba_fails:
  3081 000063FA F9                  <1> 	stc
  3082                              <1> rwdsk_lba_ok:
  3083 000063FB 5B                  <1> 	pop	ebx ; ***
  3084 000063FC 5E                  <1> 	pop	esi ; ****
  3085 000063FD C3                  <1> 	retn
  3086                              <1> rwdsk_lba_reset:
  3087 000063FE B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3088                              <1> 	;int	13h
  3089 00006400 E851C3FFFF          <1>         call	int13h
  3090 00006405 73D7                <1> 	jnc     short rwdsk_lba_retry
  3091 00006407 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3092 00006409 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3093                              <1> 	;
  3094                              <1> 	; CHS read (convert LBA address to CHS values)	
  3095                              <1> rwdsk_chs:
  3096                              <1> 	; 10/07/2015
  3097 0000640B 81EE[7A6B0000]      <1> 	sub	esi, drv.status
  3098 00006411 89F1                <1> 	mov	ecx, esi
  3099 00006413 81C6[816B0000]      <1> 	add 	esi, drv.error
  3100                              <1> 	; 02/07/2015
  3101                              <1> 	; 16/06/2015
  3102                              <1>  	; 11/06/2015 
  3103 00006419 53                  <1> 	push	ebx ; ** ; buffer
  3104 0000641A D1E1                <1> 	shl	ecx, 1
  3105 0000641C 51                  <1> 	push	ecx ; * 
  3106                              <1> 	;
  3107 0000641D 89CB                <1> 	mov	ebx, ecx
  3108 0000641F 8835[09720000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3109 00006425 31D2                <1> 	xor	edx, edx ; 0
  3110 00006427 29C9                <1> 	sub	ecx, ecx 
  3111 00006429 81C3[506B0000]      <1>         add     ebx, drv.spt
  3112 0000642F 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3113                              <1> 		; EDX:EAX = LBA
  3114                              <1> ; 28/11/2021 - temporary
  3115 00006432 09C9                <1> or ecx, ecx
  3116 00006434 7515                <1> jnz short bunugec1
  3117 00006436 50                  <1> push	eax
  3118 00006437 B44E                <1> mov	ah, 4Eh
  3119 00006439 B021                <1> mov	al, '!'
  3120 0000643B 66A300800B00        <1> mov	[0B8000h], ax
  3121 00006441 B9FFFFFF0F          <1> mov	ecx, 0FFFFFFFh
  3122                              <1> above4:
  3123 00006446 4A                  <1> dec	edx
  3124 00006447 42                  <1> inc	edx
  3125 00006448 E2FC                <1> loop	above4
  3126 0000644A 58                  <1> pop	eax
  3127                              <1> 
  3128                              <1> bunugec1: 
  3129                              <1> 
  3130 0000644B F7F1                <1> 	div	ecx
  3131 0000644D 88D1                <1> 	mov	cl, dl	; sector number - 1
  3132 0000644F FEC1                <1> 	inc	cl	; sector number (1 based)
  3133 00006451 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3134 00006452 51                  <1> 	push	ecx ; 28/11/2021
  3135 00006453 81C3[426B0000]      <1>         add     ebx, drv.heads
  3136 00006459 668B0B              <1> 	mov	cx, [ebx] ; heads
  3137 0000645C 31D2                <1> 	xor	edx, edx
  3138                              <1> 		; EAX = cylinders * heads + head
  3139 0000645E F7F1                <1> 	div	ecx
  3140                              <1> 	;pop	cx     ; sector number
  3141 00006460 59                  <1> 	pop	ecx ; 28/11/2021
  3142 00006461 88D6                <1> 	mov	dh, dl ; head number
  3143 00006463 8A15[2B6B0000]      <1> 	mov	dl, [drv]
  3144 00006469 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3145 0000646B C0E406              <1> 	shl	ah, 6
  3146 0000646E 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3147                              <1> 		       ; sector (bits 0-7)
  3148 00006470 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3149                              <1> 		; CL = sector (bits 0-5)
  3150                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3151                              <1> 		; CH = cylinder (bits 0-7)
  3152                              <1> 		; DH = head
  3153                              <1> 		; DL = drive
  3154                              <1> 	;
  3155 00006471 C605[0B720000]04    <1> 	mov	byte [retry_count], 4
  3156                              <1> rwdsk_retry:	
  3157 00006478 8A25[09720000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3158 0000647E B001                <1> 	mov	al, 1 ; sector count	
  3159                              <1> 	;int	13h
  3160 00006480 E8D1C2FFFF          <1> 	call	int13h
  3161 00006485 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3162 00006487 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3163 00006489 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3164 0000648C 7408                <1> 	je	short rwdsk_fails
  3165 0000648E FE0D[0B720000]      <1> 	dec	byte [retry_count]
  3166 00006494 7504                <1> 	jnz	short rwdsk_reset
  3167                              <1> rwdsk_fails:
  3168 00006496 F9                  <1> 	stc
  3169                              <1> rwdsk_ok:
  3170 00006497 5B                  <1> 	pop	ebx ; ***
  3171 00006498 5E                  <1> 	pop	esi ; ****
  3172 00006499 C3                  <1> 	retn
  3173                              <1> rwdsk_reset:
  3174                              <1> 	; 02/02/2015
  3175 0000649A 28E4                <1> 	sub	ah, ah
  3176 0000649C 80FA80              <1> 	cmp	dl, 80h
  3177 0000649F 7202                <1> 	jb	short rwdsk_fd_reset
  3178 000064A1 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3179                              <1> rwdsk_fd_reset:
  3180                              <1> 	;int	13h
  3181 000064A3 E8AEC2FFFF          <1>         call	int13h
  3182 000064A8 73CE                <1> 	jnc	short rwdsk_retry
  3183 000064AA 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3184 000064AC EBE9                <1> 	jmp 	short rwdsk_ok
  3185                              <1> 
  3186                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3187                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3188                              <1> ;
  3189                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3190                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3191                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3192                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3193                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3194                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3195                              <1> ; as in original unix v1.
  3196                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3197                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3198                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3199                              <1> ;
  3200                              <1> ; Erdogan tan (10/07/2015) 
  3201                              <1> 
  3202                              <1> ;drum: / interrupt handler
  3203                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3204                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3205                              <1> ;                                      / error
  3206                              <1> ;               br 3f / no, error
  3207                              <1> ;       br      2f / error
  3208                              <1> ;
  3209                              <1> ;disk:
  3210                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3211                              <1> ;       jmp     *$0f
  3212                              <1> ;0:
  3213                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3214                              <1> ;      	        br 3f / no, errors
  3215                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3216                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3217                              <1> ;                        / to 1f
  3218                              <1> ;       br      4f
  3219                              <1> ;1:
  3220                              <1> ;       bit     $20000,rkcs
  3221                              <1> ;       beq     4f / wait for seek complete
  3222                              <1> ;       mov     $0b,0b-2
  3223                              <1> ;       mov     rkap,r1
  3224                              <1> ;2:
  3225                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3226                              <1> ;                          / the disk buffer
  3227                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3228                              <1> ;       inc     r1
  3229                              <1> ;       asr     (r1)
  3230                              <1> ;       asr     (r1)
  3231                              <1> ;       asr     (r1) / reissue request
  3232                              <1> ;       dec     r1
  3233                              <1> ;3:
  3234                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3235                              <1> ;       mov     ac,-(sp)
  3236                              <1> ;       mov     mq,-(sp) / put these on the stack
  3237                              <1> ;       mov     sc,-(sp)
  3238                              <1> ;       jsr     r0,poke
  3239                              <1> ;       mov     (sp)+,sc
  3240                              <1> ;       mov     (sp)+,mq / pop them off stack
  3241                              <1> ;       mov     (sp)+,ac
  3242                              <1> ;4:
  3243                              <1> ;       jmp     retisp / u4-3
  3244                              <1> ;
  3245                              <1> ;trapt:                  / r2 points to the
  3246                              <1> ;       mov     (r0)+,r2 / device control register
  3247                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3248                              <1> ;       tst     (sp)+
  3249                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3250                              <1> ;       bge     4b / device still active so branch
  3251                              <1> ;       bit     (r0),active / was device busy?
  3252                              <1> ;       beq     4b / no, stray interrupt
  3253                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3254                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3255                              <1> ;       bge     2f / if no error jump to 2f
  3256                              <1> ;       tst     (r0)+ / skip on error
  3257                              <1> ; 2:
  3258                              <1> ;       jmp     (r0)
  2028                                  %include 'u9.s'      ; 29/06/2015
  2029                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2030                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2031                              <1> ; ****************************************************************************
  2032                              <1> ; Retro UNIX 386 v1 Kernel (v0.2) - SYS9.INC
  2033                              <1> ; Last Modification: 24/12/2021
  2034                              <1> ; ----------------------------------------------------------------------------
  2035                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2036                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2037                              <1> ;
  2038                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2039                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2040                              <1> ; <Bell Laboratories (17/3/1972)>
  2041                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2042                              <1> ;
  2043                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2044                              <1> ;
  2045                              <1> ; ****************************************************************************
  2046                              <1> 
  2047                              <1> getch:
  2048                              <1> 	; 30/06/2015
  2049                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2050 000064AE 28C0                <1> 	sub	al, al ; 0
  2051                              <1> getch_q: ; 06/08/2015
  2052 000064B0 8A25[66700000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2053 000064B6 EB06                <1>         jmp     short getc_n
  2054                              <1> 
  2055                              <1> getc: 
  2056                              <1> 	; 12/11/2015
  2057                              <1> 	; 15/09/2015
  2058                              <1> 	; 01/07/2015
  2059                              <1> 	; 30/06/2015
  2060                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2061                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2062                              <1> 	;
  2063                              <1> 	; Retro UNIX 8086 v1 modification !
  2064                              <1> 	; 
  2065                              <1> 	; 'getc' gets (next) character 
  2066                              <1> 	;	 from requested TTY (keyboard) buffer 
  2067                              <1> 	; INPUTS ->
  2068                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2069                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2070                              <1> 	;	(Keyboard buffer will point to 
  2071                              <1> 	;			next character at next call)
  2072                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2073                              <1> 	;	(Keyboard buffer will point to 
  2074                              <1> 	;			current character at next call)
  2075                              <1> 	; OUTPUTS ->
  2076                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2077                              <1> 	;     			 ZF=0 -> AX has (current) character
  2078                              <1> 	;      AL = ascii code
  2079                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2080                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2081                              <1> 	; Original UNIX V1 'getc': 
  2082                              <1> 	;		get a character off character list
  2083                              <1> 	;
  2084                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2085                              <1> 	;
  2086                              <1> 	; 30/06/20045 (32 bit modifications)
  2087                              <1> 	; 16/07/2013
  2088                              <1> 	; mov 	[getctty], ah
  2089                              <1> 	;
  2090                              <1> 
  2091 000064B8 8A25[6D710000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2092                              <1> getc_n:
  2093                              <1> 	; 30/06/2015
  2094 000064BE 08E4                <1> 	or	ah, ah
  2095 000064C0 740D                <1> 	jz	short getc0 
  2096 000064C2 D0E4                <1> 	shl	ah, 1
  2097 000064C4 0FB6DC              <1> 	movzx	ebx, ah
  2098 000064C7 81C3[68700000]      <1> 	add	ebx, ttychr
  2099 000064CD EB05                <1> 	jmp	short getc1
  2100                              <1> getc0:
  2101 000064CF BB[68700000]        <1> 	mov	ebx, ttychr
  2102                              <1> getc1:
  2103 000064D4 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2104                              <1> 				; (by kb_int)	
  2105 000064D7 6609C9              <1> 	or	cx, cx
  2106 000064DA 7507                <1> 	jnz	short getc2
  2107 000064DC 20C0                <1> 	and 	al, al
  2108 000064DE 7415                <1> 	jz	short getc_s
  2109                              <1> 	;xor	ax, ax
  2110                              <1> 	; 30/11/2021
  2111 000064E0 31C0                <1> 	xor	eax, eax
  2112 000064E2 C3                  <1> 	retn
  2113                              <1> getc2:	
  2114 000064E3 20C0                <1> 	and	al, al
  2115 000064E5 6689C8              <1> 	mov	ax, cx
  2116 000064E8 66B90000            <1> 	mov	cx, 0
  2117 000064EC 7506                <1> 	jnz	short getc3
  2118                              <1> getc_sn:
  2119 000064EE 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2120 000064F1 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2121                              <1> getc3:
  2122 000064F4 C3                  <1> 	retn
  2123                              <1> getc_s:
  2124                              <1> 	; 12/11/2015
  2125                              <1> 	; 15/09/2015
  2126                              <1> 	; 01/07/2015
  2127                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2129                              <1> 	;
  2130                              <1> 	; tty  of the current process is not 
  2131                              <1> 	; current tty (ptty); so, current process only 
  2132                              <1> 	; can use keyboard input when its tty becomes 
  2133                              <1> 	; current tty (ptty).
  2134                              <1> 	; 'sleep' is for preventing an endless lock
  2135                              <1> 	; during this tty input request.
  2136                              <1> 	; (Because, the user is not looking at the video page
  2137                              <1> 	; of the process to undersand there is a keyboard
  2138                              <1> 	; input request.)
  2139                              <1> 	;
  2140                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2141                              <1> 	;
  2142                              <1> 	; 05/10/2013
  2143                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2144                              <1> 	;
  2145                              <1> 	; 10/10/2013
  2146                              <1> gcw0:
  2147 000064F5 B10A                <1> 	mov	cl, 10 ; ch = 0
  2148                              <1> gcw1:	
  2149                              <1> 	; 12/11/2015
  2150 000064F7 E8EBD8FFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2151                              <1> 	; 10/10/2013
  2152 000064FC E8A1ECFFFF          <1> 	call	idle
  2153 00006501 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2154                              <1> 				; (by kb_int)
  2155 00006504 6609C0              <1> 	or	ax, ax
  2156                              <1> ;	jnz	short gcw3
  2157 00006507 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2158                              <1> 	; 30/06/2015
  2159 00006509 FEC9                <1> 	dec	cl
  2160 0000650B 75EA                <1> 	jnz	short gcw1
  2161                              <1> 	;
  2162 0000650D 8A25[6D710000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2163                              <1> ;	; 10/12/2013
  2164                              <1> ;	cmp 	ah, [ptty]
  2165                              <1> ;	jne	short gcw2
  2166                              <1> ;	; 14/02/2014
  2167                              <1> ;	cmp	byte [u.uno], 1
  2168                              <1> ;	jna	short gcw0		
  2169                              <1> ;gcw2:
  2170 00006513 E81DEDFFFF          <1> 	call	sleep
  2171                              <1> 	;
  2172                              <1> 	; 20/09/2013
  2173 00006518 8A25[6D710000]      <1> 	mov	ah, [u.ttyn]
  2174 0000651E 30C0                <1> 	xor 	al, al
  2175 00006520 EB9C                <1> 	jmp	short getc_n
  2176                              <1> ;gcw3:
  2177                              <1> gcw2: 	; 15/09/2015
  2178                              <1> 	; 10/10/2013
  2179 00006522 30C9                <1> 	xor	cl, cl
  2180 00006524 EBC8                <1> 	jmp	short getc_sn
  2181                              <1> 
  2182                              <1> putc:	
  2183                              <1> 	; 05/12/2021 (Retro UNIX 386 v1.2)
  2184                              <1> 	; 13/08/2015
  2185                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2186                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2187                              <1> 	;
  2188                              <1> 	; Retro UNIX 8086 v1 modification !
  2189                              <1> 	; 
  2190                              <1> 	; 'putc' puts a character 
  2191                              <1> 	;	 onto requested (tty) video page or
  2192                              <1> 	;	 serial port
  2193                              <1> 	; INPUTS ->
  2194                              <1> 	;     AL = ascii code of the character
  2195                              <1> 	;     AH = video page (tty) number (0 to 7)
  2196                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2197                              <1> 	; OUTPUTS ->
  2198                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2199                              <1> 	;      			ZF=0 -> AX has (current) character
  2200                              <1> 	;     cf=0 and AH = 0 -> no error
  2201                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)
  2202                              <1> 	; 
  2203                              <1> 	; Original UNIX V1 'putc': 
  2204                              <1> 	;     put a character at the end of character list
  2205                              <1> 	;
  2206                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2207                              <1> 	;
  2208 00006526 80FC07              <1> 	cmp	ah, 7
  2209 00006529 770A                <1>         ja      short sndc ; 05/12/2021
  2210                              <1> 	; 30/06/2015
  2211 0000652B 0FB6DC              <1> 	movzx	ebx, ah
  2212                              <1> 	; 13/08/2015
  2213 0000652E B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2214 00006530 E98AAFFFFF          <1> 	jmp	write_tty ; 'video.inc'
  2215                              <1> 
  2216                              <1> sndc:   ; <Send character>
  2217                              <1> 	;
  2218                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2219                              <1> 	; 17/11/2015
  2220                              <1> 	; 16/11/2015
  2221                              <1> 	; 11/11/2015
  2222                              <1> 	; 10/11/2015
  2223                              <1> 	; 09/11/2015
  2224                              <1> 	; 08/11/2015
  2225                              <1> 	; 07/11/2015
  2226                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2227                              <1> 	; 29/10/2015
  2228                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2229                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2230                              <1> 	;
  2231                              <1> 	; Retro UNIX 8086 v1 feature only !
  2232                              <1> 	;
  2233                              <1> 	; ah = [u.ttyn]
  2234                              <1> 	;
  2235                              <1> 	; 30/06/2015
  2236 00006535 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2237                              <1> 	; 07/11/2015
  2238 00006538 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2239                              <1> sndc0:
  2240                              <1> 	; 07/11/2015
  2241 0000653B E84BEDFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2242 00006540 7405                <1> 	jz	short sndc1
  2243 00006542 E8A0D8FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2244                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2245                              <1> sndc1:
  2246                              <1> 	; 16/11/2015
  2247                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2248                              <1> 	; 24/12/2021
  2249 00006547 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2250                              <1> sndcx:
  2251 00006549 8A83[AA700000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2252 0000654F 8AA3[A8700000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2253                              <1> 	;
  2254                              <1> 	; 17/11/2015
  2255                              <1> 	; check 'request for response' status
  2256 00006555 80BB[A4700000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2257 0000655C 740A                <1> 	jz	short query
  2258                              <1> response:
  2259 0000655E FE05[A7700000]      <1> 	inc 	byte [comqr] ; query or response status
  2260 00006564 B0FF                <1> 	mov	al, 0FFh	 
  2261 00006566 EB14                <1> 	jmp	short sndc3
  2262                              <1> query:
  2263 00006568 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2264 0000656A 750E                <1> 	jnz 	short sndc2 ; normal character
  2265                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2266                              <1> 	;je	short sndc2  ; yes, already responded
  2267                              <1> 	; 16/11/2015
  2268                              <1> 	; query: request for response (again)
  2269 0000656C 8883[A8700000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2270 00006572 FE05[A7700000]      <1> 	inc 	byte [comqr] ; query or response status
  2271 00006578 EB02                <1> 	jmp	short sndc3
  2272                              <1> sndc2:
  2273 0000657A 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2274                              <1> sndc3:
  2275 0000657C 8883[AA700000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2276 00006582 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2277                              <1> 	; 30/06/2015
  2278 00006584 E8D0D1FFFF          <1> 	call	sp_status ; get serial port status
  2279                              <1> 	; AL = Line status, AH = Modem status
  2280                              <1> 	; 07/11/2015
  2281 00006589 A880                <1> 	test	al, 80h
  2282 0000658B 7504                <1> 	jnz	short sndc4
  2283 0000658D A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2284 0000658F 751B                <1> 	jnz	short sndc5
  2285                              <1> sndc4: 	; Check line status again
  2286                              <1> 	; 16/11/2015
  2287                              <1> 	;push	cx
  2288                              <1> 	; 24/12/2021
  2289 00006591 51                  <1> 	push	ecx
  2290 00006592 B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2291 00006597 E832B0FFFF          <1> 	call	WAITF
  2292                              <1> 	;pop	cx
  2293                              <1> 	; 24/12/1021
  2294 0000659C 59                  <1> 	pop	ecx
  2295                              <1> 	;
  2296 0000659D 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2297 0000659F E8B5D1FFFF          <1> 	call	sp_status ; get serial port status
  2298                              <1> 	; 16/11/2015
  2299                              <1> 	; 09/11/2015
  2300                              <1> 	; 08/11/2015
  2301 000065A4 A880                <1> 	test	al, 80h	; time out error
  2302 000065A6 7566                <1>         jnz     short sndc7
  2303 000065A8 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2304 000065AA 7462                <1>         jz	short sndc7
  2305                              <1> sndc5:  
  2306 000065AC 8A83[AA700000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2307 000065B2 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2308 000065B6 28DE                <1> 	sub	dh, bl
  2309 000065B8 EE                  <1> 	out	dx, al	   ; send on serial port
  2310                              <1> 	; 10/11/2015
  2311                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2312                              <1> 	; (to improve text flow to the terminal)
  2313                              <1> 	; ('diskette.inc': 'WAITF')
  2314                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2315                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2316                              <1> 	;push	cx
  2317                              <1> 	; 24/12/2021
  2318 000065B9 51                  <1> 	push	ecx
  2319 000065BA B906000000          <1> 	mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2320 000065BF E80AB0FFFF          <1> 	call	WAITF
  2321                              <1> 	;pop	cx
  2322                              <1> 	; 24/12/1021
  2323 000065C4 59                  <1> 	pop	ecx
  2324                              <1>     	;
  2325                              <1> 	; 07/11/2015
  2326 000065C5 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2327                              <1> 	;
  2328 000065C7 E88DD1FFFF          <1> 	call	sp_status ; get serial port status
  2329                              <1> 	; AL = Line status, AH = Modem status
  2330                              <1> 	;
  2331 000065CC E8BAECFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2332 000065D1 7405                <1> 	jz	short sndc6
  2333 000065D3 E80FD8FFFF          <1> 	call	intract ; quit (ctrl+break) check
  2334                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2335                              <1> sndc6:
  2336 000065D8 3C80                <1> 	cmp	al, 80h
  2337 000065DA 7332                <1> 	jnb	short sndc7		
  2338                              <1> 	;
  2339 000065DC 803D[A7700000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2340 000065E3 7244                <1> 	jb	short sndc8 	; no, normal character
  2341 000065E5 883D[A7700000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2342                              <1> 	; 17/11/2015
  2343 000065EB E8B2EBFFFF          <1> 	call	idle
  2344                              <1> 	;
  2345 000065F0 38BB[AA700000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2346                              <1>         ;ja	sndc2       ; response (will be followed by
  2347                              <1> 			    ; a normal character)
  2348                              <1> 	; 24/12/2021
  2349 000065F6 7602                <1> 	jna	short sndc_10
  2350 000065F8 EB80                <1> 	jmp	sndc2
  2351                              <1> sndc_10:
  2352                              <1> 	; Query request must be responded by the terminal
  2353                              <1> 	; before sending a normal character !
  2354 000065FA 53                  <1> 	push	ebx
  2355                              <1> 	;push	cx ; *** cl = character (to be sent)
  2356                              <1> 	; 24/12/2021
  2357 000065FB 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2358 000065FC 8A25[6D710000]      <1> 	mov	ah, [u.ttyn]
  2359 00006602 E82EECFFFF          <1> 	call	sleep ; this process will be awakened by
  2360                              <1> 		      ; received data available interrupt
  2361                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2362                              <1> 	; 24/12/2021
  2363 00006607 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2364 00006608 5B                  <1> 	pop	ebx
  2365 00006609 E93BFFFFFF          <1>         jmp	sndcx
  2366                              <1> sndc7:
  2367                              <1> 	 ; 16/11/2015
  2368 0000660E 803D[A7700000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2369 00006615 7213                <1> 	jb	short sndc9 	; no
  2370                              <1> 	;
  2371 00006617 88BB[A8700000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2372 0000661D 88BB[AA700000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2373                              <1> 	;
  2374 00006623 883D[A7700000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2375                              <1> sndc8:
  2376 00006629 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2377                              <1> sndc9:
  2378                              <1> 	; AL = Line status, AH = Modem status
  2379 0000662A C3                  <1> 	retn
  2380                              <1> 
  2381                              <1> get_cpos:
  2382                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2383                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2384                              <1> 	;
  2385                              <1> 	; INPUT -> bl = video page number
  2386                              <1> 	; RETURN -> dx = cursor position
  2387                              <1> 
  2388 0000662B 53                  <1> 	push	ebx
  2389 0000662C 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2390 0000662F D0E3                <1> 	shl	bl, 1
  2391 00006631 81C3[56700000]      <1> 	add	ebx, cursor_posn
  2392 00006637 668B13              <1> 	mov	dx, [ebx]
  2393 0000663A 5B                  <1> 	pop	ebx
  2394 0000663B C3                  <1> 	retn
  2395                              <1> 
  2396                              <1> read_ac_current:
  2397                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2398                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2399                              <1> 	;
  2400                              <1> 	; INPUT -> bl = video page number
  2401                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2402                              <1> 
  2403 0000663C E8FCAFFFFF          <1> 	call 	find_position ; 'video.inc'
  2404                              <1> 	; dx = status port
  2405                              <1> 	; esi = cursor location/address
  2406 00006641 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2407 00006647 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2408 0000664A C3                  <1> 	retn
  2409                              <1> 
  2410                              <1> syssleep:
  2411                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2412                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2413                              <1> 	;
  2414                              <1> 	; Retro UNIX 8086 v1 feature only
  2415                              <1> 	; (INPUT -> none)
  2416                              <1> 	;
  2417 0000664B 0FB61D[89710000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2418 00006652 8AA3[6F6E0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2419 00006658 E8D8EBFFFF          <1> 	call	sleep
  2420 0000665D E985D6FFFF          <1> 	jmp	sysret
  2421                              <1> 
  2422                              <1> vp_clr:
  2423                              <1> 	; Reset/Clear Video Page
  2424                              <1> 	;
  2425                              <1> 	; 05/12/2021 - (Retro UNIX 386 v1.2)
  2426                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2427                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2428                              <1> 	;
  2429                              <1> 	; Retro UNIX 8086 v1 feature only !
  2430                              <1> 	;
  2431                              <1> 	; INPUTS -> 
  2432                              <1> 	;   BL = video page number	 
  2433                              <1> 	;
  2434                              <1> 	; OUTPUT ->
  2435                              <1> 	;   none
  2436                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2437                              <1> 	;
  2438                              <1> 	; 04/12/2013
  2439 00006662 28C0                <1> 	sub	al, al
  2440                              <1> 	; al = 0 (clear video page)
  2441                              <1> 	; bl = video page
  2442 00006664 B407                <1> 	mov	ah, 07h
  2443                              <1> 	; ah = 7 (attribute/color)
  2444                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2445                              <1> 	; 05/12/2021
  2446 00006666 31C9                <1> 	xor	ecx, ecx
  2447 00006668 66BA4F18            <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2448 0000666C E8F6AFFFFF          <1> 	call	scroll_up
  2449                              <1> 	; bl = video page
  2450                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2451                              <1> 	; 05/12/2021
  2452 00006671 31D2                <1> 	xor	edx, edx
  2453 00006673 E969AFFFFF          <1> 	jmp 	set_cpos
  2454                              <1> 
  2455                              <1> sysmsg:
  2456                              <1> 	; 11/12/2021
  2457                              <1> 	; 04/12/2021 (Retro UNIX 386 v1.2)
  2458                              <1> 	; 11/11/2015
  2459                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2460                              <1> 	; Print user-application message on user's console tty
  2461                              <1> 	;
  2462                              <1> 	; Input -> EBX = Message address
  2463                              <1> 	;	   ECX = Message length (max. 255)
  2464                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2465                              <1> 	;
  2466 00006678 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2467                              <1> 	;ja	sysret ; nothing to do with big message size
  2468 0000667E 7779                <1> 	ja	short sysmsg8 ; 11/12/2021
  2469 00006680 08C9                <1> 	or	cl, cl
  2470                              <1> 	;jz	sysret
  2471 00006682 7475                <1> 	jz	short sysmsg8 ; 11/12/2021
  2472 00006684 20D2                <1> 	and	dl, dl
  2473 00006686 7502                <1> 	jnz	short sysmsg0
  2474 00006688 B207                <1> 	mov	dl, 07h ; default color
  2475                              <1> 		; (black background, light gray character)
  2476                              <1> sysmsg0:
  2477 0000668A 891D[5C710000]      <1> 	mov	[u.base], ebx
  2478 00006690 8815[67700000]      <1> 	mov	[ccolor], dl ; color attributes
  2479 00006696 89E5                <1> 	mov	ebp, esp
  2480 00006698 31DB                <1> 	xor	ebx, ebx ; 0
  2481 0000669A 891D[64710000]      <1> 	mov	[u.nread], ebx ; 0
  2482                              <1> 	;
  2483 000066A0 381D[AA710000]      <1> 	cmp	[u.kcall], bl ; 0
  2484 000066A6 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2485                              <1> 	;
  2486 000066A8 890D[60710000]      <1> 	mov	[u.count], ecx
  2487 000066AE 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ ; 04/12/2021
  2488                              <1> 	; 04/12/2021
  2489                              <1> 	; (dword alignment for esp)
  2490 000066AF F6C103              <1> 	test	cl, 3
  2491 000066B2 7404                <1> 	jz	short sysmsg_7
  2492 000066B4 80C903              <1> 	or	cl, 3
  2493 000066B7 41                  <1> 	inc	ecx
  2494                              <1> sysmsg_7:
  2495 000066B8 29CC                <1> 	sub	esp, ecx
  2496 000066BA 89E7                <1> 	mov	edi, esp
  2497 000066BC 89E6                <1> 	mov	esi, esp
  2498 000066BE 66891D[A4710000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2499                              <1> 	; 11/11/2015
  2500 000066C5 8A25[6E710000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2501                              <1> 	; 0 = none
  2502 000066CB FECC                <1> 	dec	ah
  2503 000066CD 790C                <1> 	jns	short sysmsg1 
  2504 000066CF 8A1D[89710000]      <1> 	mov	bl, [u.uno] ; process number	
  2505 000066D5 8AA3[6F6E0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2506                              <1> sysmsg1:
  2507 000066DB 8825[6D710000]      <1> 	mov	[u.ttyn], ah
  2508                              <1> sysmsg2:
  2509 000066E1 E836F5FFFF          <1> 	call	cpass
  2510 000066E6 7416                <1> 	jz	short sysmsg5
  2511 000066E8 AA                  <1> 	stosb
  2512 000066E9 20C0                <1> 	and	al, al
  2513 000066EB 75F4                <1> 	jnz	short sysmsg2
  2514                              <1> sysmsg3:
  2515 000066ED 80FC07              <1> 	cmp	ah, 7 ; tty number
  2516 000066F0 7711                <1> 	ja	short sysmsg6 ; serial port
  2517 000066F2 E83E000000          <1> 	call	print_cmsg
  2518                              <1> sysmsg4:
  2519 000066F7 89EC                <1> 	mov	esp, ebp
  2520                              <1> sysmsg8: ; 11/12/2021	
  2521 000066F9 E9E9D5FFFF          <1> 	jmp	sysret
  2522                              <1> sysmsg5:
  2523 000066FE C60700              <1> 	mov	byte [edi], 0
  2524 00006701 EBEA                <1> 	jmp	short sysmsg3
  2525                              <1> sysmsg6:
  2526 00006703 8A06                <1> 	mov	al, [esi]
  2527 00006705 E82BFEFFFF          <1> 	call	sndc
  2528 0000670A 72EB                <1> 	jc	short sysmsg4
  2529 0000670C 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2530 0000670F 76E6                <1> 	jna	short sysmsg4
  2531 00006711 46                  <1> 	inc 	esi
  2532 00006712 8A25[6D710000]      <1> 	mov	ah, [u.ttyn]
  2533 00006718 EBE9                <1> 	jmp	short sysmsg6
  2534                              <1> 
  2535                              <1> sysmsgk: ; Temporary (01/07/2015)
  2536                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2537                              <1> 	; (ECX -character count- will not be considered)
  2538 0000671A 8B35[5C710000]      <1> 	mov	esi, [u.base]
  2539 00006720 8A25[66700000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2540 00006726 8825[6D710000]      <1> 	mov	[u.ttyn], ah
  2541 0000672C C605[AA710000]00    <1> 	mov	byte [u.kcall], 0
  2542 00006733 EBB8                <1> 	jmp	short sysmsg3
  2543                              <1> 	
  2544                              <1> print_cmsg: 
  2545                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2546                              <1> 	;
  2547                              <1> 	; print message (on user's console tty) 
  2548                              <1> 	;	with requested color
  2549                              <1> 	;
  2550                              <1> 	; INPUTS:
  2551                              <1> 	;	esi = message address
  2552                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2553                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2554                              <1> 	;
  2555 00006735 AC                  <1> 	lodsb
  2556                              <1> pcmsg1:
  2557 00006736 56                  <1> 	push 	esi
  2558 00006737 0FB61D[6D710000]    <1>         movzx   ebx, byte [u.ttyn]
  2559 0000673E 8A25[67700000]      <1> 	mov	ah, [ccolor]
  2560 00006744 E876ADFFFF          <1> 	call 	write_tty
  2561 00006749 5E                  <1> 	pop	esi
  2562 0000674A AC                  <1> 	lodsb
  2563 0000674B 20C0                <1> 	and 	al, al  ; 0
  2564 0000674D 75E7                <1> 	jnz 	short pcmsg1
  2565 0000674F C3                  <1> 	retn
  2566                              <1> 
  2567                              <1> sysgeterr:
  2568                              <1> 	; 09/12/2015
  2569                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2570                              <1> 	; Get last error number or page fault count
  2571                              <1> 	; (for debugging)
  2572                              <1> 	;
  2573                              <1> 	; Input -> EBX = return type
  2574                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2575                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2576                              <1> 	;	   FFFFFFFEh = total page fault count
  2577                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2578                              <1> 	;
  2579                              <1> 	; Output -> EAX = last error number or page fault count
  2580                              <1> 	;	   (depending on EBX input)
  2581                              <1> 	; 	
  2582 00006750 21DB                <1> 	and 	ebx, ebx
  2583 00006752 750B                <1> 	jnz	short glerr_2
  2584                              <1> glerr_0:
  2585 00006754 A1[AC710000]        <1> 	mov	eax, [u.error]
  2586                              <1> glerr_1:
  2587 00006759 A3[34710000]        <1> 	mov	[u.r0], eax
  2588 0000675E C3                  <1>  	retn
  2589                              <1> glerr_2:
  2590 0000675F 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2591 00006760 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2592 00006762 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2593 00006763 75EF                <1> 	jnz	short glerr_0
  2594 00006765 A1[34760000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2595 0000676A EBED                <1>         jmp     short glerr_1
  2596                              <1> glerr_3:
  2597 0000676C A1[B0710000]        <1> 	mov 	eax, [u.pfcount]
  2598 00006771 EBE6                <1> 	jmp	short glerr_1
  2029                                  
  2030                                  ; 07/03/2015
  2031                                  ; Temporary Code
  2032                                  display_disks:
  2033 00006773 803D[2E6B0000]00        	cmp 	byte [fd0_type], 0
  2034 0000677A 7605                    	jna 	short ddsks1
  2035 0000677C E87D000000              	call	pdskm
  2036                                  ddsks1:
  2037 00006781 803D[2F6B0000]00        	cmp	byte [fd1_type], 0
  2038 00006788 760C                    	jna	short ddsks2
  2039 0000678A C605[1F6D0000]31        	mov	byte [dskx], '1'
  2040 00006791 E868000000              	call	pdskm
  2041                                  ddsks2:
  2042 00006796 803D[306B0000]00        	cmp	byte [hd0_type], 0
  2043 0000679D 7654                    	jna	short ddsk6
  2044 0000679F 66C705[1D6D0000]68-     	mov	word [dsktype], 'hd'
  2044 000067A7 64                 
  2045 000067A8 C605[1F6D0000]30        	mov	byte [dskx], '0'
  2046 000067AF E84A000000              	call	pdskm
  2047                                  ddsks3:
  2048 000067B4 803D[316B0000]00        	cmp	byte [hd1_type], 0
  2049 000067BB 7636                    	jna	short ddsk6
  2050 000067BD C605[1F6D0000]31        	mov	byte [dskx], '1'
  2051 000067C4 E835000000              	call	pdskm
  2052                                  ddsks4:
  2053 000067C9 803D[326B0000]00        	cmp	byte [hd2_type], 0
  2054 000067D0 7621                    	jna	short ddsk6
  2055 000067D2 C605[1F6D0000]32        	mov	byte [dskx], '2'
  2056 000067D9 E820000000              	call	pdskm
  2057                                  ddsks5:
  2058 000067DE 803D[336B0000]00        	cmp	byte [hd3_type], 0
  2059 000067E5 760C                    	jna	short ddsk6
  2060 000067E7 C605[1F6D0000]33        	mov	byte [dskx], '3'
  2061 000067EE E80B000000              	call	pdskm
  2062                                  ddsk6:
  2063 000067F3 BE[2E6D0000]            	mov	esi, nextline
  2064 000067F8 E806000000              	call	pdskml
  2065                                  pdskm_ok:
  2066 000067FD C3                      	retn
  2067                                  pdskm:
  2068 000067FE BE[1B6D0000]            	mov	esi, dsk_ready_msg
  2069                                  pdskml:	
  2070 00006803 AC                      	lodsb
  2071 00006804 08C0                    	or	al, al
  2072 00006806 74F5                    	jz	short pdskm_ok
  2073 00006808 56                      	push	esi
  2074 00006809 31DB                    	xor	ebx, ebx ; 0
  2075                                  			; Video page 0 (bl=0)
  2076 0000680B B407                    	mov	ah, 07h ; Black background, 
  2077                                  			; light gray forecolor
  2078 0000680D E8ADACFFFF              	call	write_tty
  2079 00006812 5E                      	pop	esi
  2080 00006813 EBEE                    	jmp	short pdskml
  2081                                  
  2082 00006815 90<rep Bh>              align 16
  2083                                  
  2084                                  gdt:	; Global Descriptor Table
  2085                                  	; (30/07/2015, conforming cs)
  2086                                  	; (26/03/2015)
  2087                                  	; (24/03/2015, tss)
  2088                                  	; (19/03/2015)
  2089                                  	; (29/12/2013)
  2090                                  	;
  2091 00006820 0000000000000000        	dw 0, 0, 0, 0	; NULL descriptor
  2092                                  	; 18/08/2014
  2093                                  			; 8h kernel code segment, base = 00000000h		
  2094 00006828 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2095                                  			; 10h kernel data segment, base = 00000000h	
  2096 00006830 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2097                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2098 00006838 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2099                                  			; 23h user data segment, base address = 400000h ; CORE
  2100 00006840 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2101                                  			; Task State Segment
  2102 00006848 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2103                                  			       ;  no IO permission in ring 3)
  2104                                  gdt_tss0:
  2105 0000684A 0000                    	dw 0  ; TSS base address, bits 0-15 
  2106                                  gdt_tss1:
  2107 0000684C 00                      	db 0  ; TSS base address, bits 16-23 
  2108                                  	      		; 49h	
  2109 0000684D E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2110 0000684E 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2111                                  gdt_tss2:
  2112 0000684F 00                      	db 0  ; TSS base address, bits 24-31 
  2113                                  
  2114                                  gdt_end:
  2115                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2116                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2117                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2118                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2119                                  
  2120                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2121                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2122                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2123                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2124                                  		; W= Writeable, A= Accessed
  2125                                  	
  2126                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2127                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2128                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2129                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2130                                  
  2131                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2132                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2133                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2134                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2135                                  	
  2136                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2137                                  
  2138                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2139                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2140                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2141                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2142                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2143                                  		; AVL= Available to programmers	
  2144                                  
  2145                                  gdtd:
  2146 00006850 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2147 00006852 [20680000]                      dd gdt			; Address of the GDT
  2148                                  
  2149                                  	; 20/08/2014
  2150                                  idtd:
  2151 00006856 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2152 00006858 [D06D0000]                      dd idt			; Address of the IDT
  2153                                  
  2154                                  Align 4
  2155                                  
  2156                                  	; 21/08/2014
  2157                                  ilist:
  2158                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2159                                  	;
  2160                                  	; Exception list
  2161                                  	; 25/08/2014	
  2162 0000685C [22090000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2163 00006860 [29090000]              	dd	exc1	
  2164 00006864 [30090000]              	dd 	exc2	
  2165 00006868 [37090000]              	dd	exc3	
  2166 0000686C [3B090000]              	dd	exc4	
  2167 00006870 [3F090000]              	dd	exc5	
  2168 00006874 [43090000]              	dd 	exc6	; 06h,  Invalid Opcode
  2169 00006878 [47090000]              	dd	exc7	
  2170 0000687C [4B090000]              	dd	exc8	
  2171 00006880 [4F090000]              	dd	exc9	
  2172 00006884 [53090000]              	dd 	exc10	
  2173 00006888 [57090000]              	dd	exc11
  2174 0000688C [5B090000]              	dd	exc12
  2175 00006890 [5F090000]              	dd	exc13	; 0Dh, General Protection Fault
  2176 00006894 [63090000]              	dd 	exc14	; 0Eh, Page Fault
  2177 00006898 [67090000]              	dd	exc15
  2178 0000689C [6B090000]              	dd	exc16
  2179 000068A0 [6F090000]              	dd	exc17
  2180 000068A4 [73090000]              	dd 	exc18
  2181 000068A8 [77090000]              	dd	exc19
  2182 000068AC [7B090000]              	dd 	exc20
  2183 000068B0 [7F090000]              	dd	exc21
  2184 000068B4 [83090000]              	dd	exc22
  2185 000068B8 [87090000]              	dd	exc23
  2186 000068BC [8B090000]              	dd 	exc24
  2187 000068C0 [8F090000]              	dd	exc25
  2188 000068C4 [93090000]              	dd	exc26
  2189 000068C8 [97090000]              	dd	exc27
  2190 000068CC [9B090000]              	dd 	exc28
  2191 000068D0 [9F090000]              	dd	exc29
  2192 000068D4 [A3090000]              	dd 	exc30
  2193 000068D8 [A7090000]              	dd	exc31
  2194                                  	; Interrupt list
  2195 000068DC [60070000]              	dd	timer_int	; INT 20h
  2196                                  		;dd	irq0	
  2197 000068E0 [5B0C0000]              	dd	keyb_int	; 27/08/2014
  2198                                  		;dd	irq1
  2199 000068E4 [7C080000]              	dd	irq2
  2200                                  		; COM2 int
  2201 000068E8 [80080000]              	dd	irq3
  2202                                  		; COM1 int
  2203 000068EC [8B080000]              	dd	irq4
  2204 000068F0 [96080000]              	dd	irq5
  2205                                  ;DISKETTE_INT: ;06/02/2015
  2206 000068F4 [03270000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2207                                  		;dd	irq6
  2208                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2209                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2210 000068F8 [0C0C0000]              	dd	default_irq7	; 25/02/2015
  2211                                  		;dd	irq7
  2212                                  ; Real Time Clock Interrupt
  2213 000068FC [B10A0000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2214                                  		;dd	irq8	; INT 28h
  2215 00006900 [A6080000]              	dd	irq9
  2216 00006904 [AA080000]              	dd	irq10
  2217 00006908 [AE080000]              	dd	irq11
  2218 0000690C [B2080000]              	dd	irq12
  2219 00006910 [B6080000]              	dd	irq13
  2220                                  ;HDISK_INT1:  ;06/02/2015 	
  2221 00006914 [292F0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2222                                  		;dd	irq14
  2223                                  ;HDISK_INT2:  ;06/02/2015
  2224 00006918 [4C2F0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2225                                  		;dd	irq15	; INT 2Fh
  2226                                  		; 14/08/2015
  2227 0000691C [CF3B0000]              	dd	sysent		; INT 30h (system calls)
  2228                                  	
  2229                                  	;dd	ignore_int
  2230 00006920 00000000                	dd	0
  2231                                  
  2232                                  ;;;
  2233                                  ;;; 11/03/2015
  2234                                  %include 'kybdata.s'	; KEYBOARD (BIOS) DATA
  2235                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2236                              <1> ; Last Modification: 11/03/2015
  2237                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2238                              <1> ;
  2239                              <1> ; ///////// KEYBOARD DATA ///////////////
  2240                              <1> 
  2241                              <1> ; 05/12/2014
  2242                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2243                              <1> ; 03/06/86  KEYBOARD BIOS
  2244                              <1> 
  2245                              <1> ;---------------------------------------------------------------------------------
  2246                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2247                              <1> ;---------------------------------------------------------------------------------
  2248                              <1> 
  2249                              <1> ;-----	TABLES FOR ALT CASE ------------
  2250                              <1> ;-----	ALT-INPUT-TABLE 
  2251 00006924 524F50514B          <1> K30:	db	82,79,80,81,75
  2252 00006929 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2253                              <1> ;-----	SUPER-SHIFT-TABLE 
  2254 0000692E 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2255 00006934 161718191E1F        <1> 	db	22,23,24,25,30,31
  2256 0000693A 202122232425        <1> 	db	32,33,34,35,36,37
  2257 00006940 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2258 00006946 3132                <1> 	db	49,50
  2259                              <1> 
  2260                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2261                              <1> ;-----	KEY_TABLE 
  2262 00006948 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2263 00006949 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2264 0000694E 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2265                              <1> _K6L    equ     $-_K6
  2266                              <1> 
  2267                              <1> ;-----	MASK_TABLE
  2268 00006950 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2269 00006951 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2270 00006956 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2271                              <1> 
  2272                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2273 00006958 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2274 0000695E 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2275 00006964 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2276 0000696A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2277 00006970 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2278 00006976 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2279 0000697C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2280 00006982 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2281 00006988 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2282 0000698E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2283                              <1> 	;				;----- FUNCTIONS ------		
  2284 00006992 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2285 00006998 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2286 0000699E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2287 000069A4 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2288 000069AA 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2289                              <1> 
  2290                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2291 000069B0 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2291 000069B9 39302D3D0809        <1>
  2292 000069BF 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2292 000069C8 705B5D0DFF61736466- <1>
  2292 000069D1 67686A6B6C3B27      <1>
  2293 000069D8 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2293 000069E1 6D2C2E2FFF2AFF20FF  <1>
  2294                              <1> ;-----	LC TABLE SCAN
  2295 000069EA 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2296 000069EF 4041424344          <1> 	db	64,65,66,67,68
  2297 000069F4 FFFF                <1> 	db	-1,-1			; NL, SL
  2298                              <1> 
  2299                              <1> ;-----	KEYPAD TABLE
  2300 000069F6 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2301 000069FC 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2302 00006A03 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2303                              <1> 
  2304                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2305 00006A08 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2305 00006A11 28295F2B0800        <1>
  2306 00006A17 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2306 00006A20 507B7D0DFF41534446- <1>
  2306 00006A29 47484A4B4C3A22      <1>
  2307 00006A30 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2307 00006A39 4D3C3E3FFF2AFF20FF  <1>
  2308                              <1> ;-----	UC TABLE SCAN
  2309 00006A42 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2310 00006A47 595A5B5C5D          <1> 	db	89,90,91,92,93
  2311 00006A4C FFFF                <1> 	db	-1,-1			; NL, SL
  2312                              <1> 
  2313                              <1> ;-----	NUM STATE TABLE
  2314 00006A4E 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2314 00006A57 3233302E            <1>
  2315                              <1> 	;
  2316 00006A5B FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2317                              <1> 
  2318                              <1> Align	4
  2319                              <1> ;----------------------------------------
  2320                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2321                              <1> ;----------------------------------------
  2322 00006A60 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2323 00006A61 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2324                              <1> 				; (29h default setting for video mode 3)
  2325                              <1> 				; Mode Select register Bits
  2326                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2327                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2328                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2329                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2330                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2331                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2332                              <1> 				;   BIT 6, 7 - Not Used
  2333                              <1> 
  2334                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2335                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2336                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2337                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2338                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2339                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2340                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2341                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2342                              <1> ; Mode & 37h = Video signal OFF
  2343                              <1> 			
  2344                              <1> 
  2345                              <1> ; 26/08/2014
  2346                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2347                              <1> ; Derived from IBM "pc-at" 
  2348                              <1> ; rombios source code (06/10/1985)
  2349                              <1> ; 'dseg.inc'
  2350                              <1> 
  2351                              <1> ;---------------------------------------;
  2352                              <1> ;	SYSTEM DATA AREA		;
  2353                              <1> ;----------------------------------------
  2354 00006A62 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2355                              <1> 
  2356                              <1> ;----------------------------------------
  2357                              <1> ;	KEYBOARD DATA AREAS		;
  2358                              <1> ;----------------------------------------
  2359                              <1> 
  2360 00006A63 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2361 00006A64 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2362 00006A65 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2363 00006A66 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2364 00006A67 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2365 00006A68 [786A0000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2366 00006A6C [986A0000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2367 00006A70 [786A0000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2368 00006A74 [786A0000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2369                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2370 00006A78 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2371                              <1> 
  2372                              <1> ; /// End Of KEYBOARD DATA ///
  2235                                  %include 'vidata.s'	; VIDEO (BIOS) DATA
  2236                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2237                              <1> ; Last Modification: 11/03/2015
  2238                              <1> ;		    (Data section for 'VIDEO.INC')	
  2239                              <1> ;
  2240                              <1> ; ///////// VIDEO DATA ///////////////
  2241                              <1> 
  2242                              <1> video_params:
  2243                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2244                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2245                              <1> 	; VIDEO MODE 3
  2246 00006A98 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2247 00006A9F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2248 00006AA4 00000000            <1> 	db	0,0,0,0
  2249                              <1> 
  2250                              <1> ; /// End Of VIDEO DATA ///
  2236                                  %include 'diskdata.s'	; DISK (BIOS) DATA (initialized)
  2237                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2238                              <1> ; Last Modification: 11/03/2015
  2239                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2240                              <1> ;
  2241                              <1> ; *****************************************************************************
  2242                              <1> 
  2243                              <1> ;----------------------------------------
  2244                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2245                              <1> ;	REFERENCED BY POST & BIOS	:
  2246                              <1> ;----------------------------------------
  2247                              <1> 
  2248 00006AA8 [0B6B0000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2249                              <1> 
  2250                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2251                              <1> ;----------------------------------------------------------------
  2252                              <1> ; DISK_BASE							:
  2253                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2254                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2255                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2256                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2257                              <1> ;----------------------------------------------------------------
  2258                              <1> 
  2259                              <1> ;DISK_BASE:	
  2260                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2261                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2262                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2263                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2264                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2265                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2266                              <1> ;	DB	01BH		; GAP LENGTH
  2267                              <1> ;	DB	0FFH		; DTL
  2268                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2269                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2270                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2271                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2272                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2273                              <1> 
  2274                              <1> ;----------------------------------------
  2275                              <1> ;	ROM BIOS DATA AREAS		:
  2276                              <1> ;----------------------------------------
  2277                              <1> 
  2278                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2279                              <1> 
  2280                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2281                              <1> 
  2282                              <1> ;----------------------------------------
  2283                              <1> ;	DISKETTE DATA AREAS		:
  2284                              <1> ;----------------------------------------
  2285                              <1> 
  2286                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2287                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2288                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2289                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2290                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2291                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2292                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2293                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2294                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2295                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2296                              <1> 
  2297                              <1> ;----------------------------------------
  2298                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2299                              <1> ;----------------------------------------
  2300                              <1> 
  2301                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2302                              <1> 
  2303                              <1> ;----------------------------------------
  2304                              <1> ;	TIMER DATA AREA 		:
  2305                              <1> ;----------------------------------------
  2306                              <1> 
  2307                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2308                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2309                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2310                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2311                              <1> 
  2312                              <1> ;----------------------------------------
  2313                              <1> ;	ADDITIONAL MEDIA DATA		:
  2314                              <1> ;----------------------------------------
  2315                              <1> 
  2316                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2317                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2318                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2319                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2320                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2321                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2322                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2323                              <1> 
  2324                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2325                              <1> 
  2326                              <1> ;--------------------------------------------------------
  2327                              <1> ;	DRIVE TYPE TABLE				:
  2328                              <1> ;--------------------------------------------------------
  2329                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2330                              <1> DR_TYPE:
  2331 00006AAC 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2332                              <1>                 ;DW	MD_TBL1
  2333 00006AAD [CA6A0000]          <1> 		dd	MD_TBL1
  2334 00006AB1 82                  <1> 		DB	02+BIT7ON
  2335                              <1> 		;DW	MD_TBL2
  2336 00006AB2 [D76A0000]          <1>                 dd      MD_TBL2
  2337 00006AB6 02                  <1> DR_DEFAULT:	DB	02
  2338                              <1>                 ;DW	MD_TBL3
  2339 00006AB7 [E46A0000]          <1> 		dd      MD_TBL3
  2340 00006ABB 03                  <1> 		DB	03
  2341                              <1>                 ;DW	MD_TBL4
  2342 00006ABC [F16A0000]          <1> 		dd      MD_TBL4
  2343 00006AC0 84                  <1> 		DB	04+BIT7ON
  2344                              <1>                 ;DW	MD_TBL5
  2345 00006AC1 [FE6A0000]          <1> 		dd      MD_TBL5
  2346 00006AC5 04                  <1> 		DB	04
  2347                              <1>                 ;DW	MD_TBL6
  2348 00006AC6 [0B6B0000]          <1> 		dd      MD_TBL6
  2349                              <1> DR_TYPE_E       equ $			; END OF TABLE
  2350                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2351                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2352                              <1> ;--------------------------------------------------------
  2353                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2354                              <1> ;--------------------------------------------------------
  2355                              <1> ;--------------------------------------------------------
  2356                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2357                              <1> ;--------------------------------------------------------
  2358                              <1> MD_TBL1:        
  2359 00006ACA DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2360 00006ACB 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2361 00006ACC 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2362 00006ACD 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2363 00006ACE 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2364 00006ACF 2A                  <1> 	DB	02AH		; GAP LENGTH
  2365 00006AD0 FF                  <1> 	DB	0FFH		; DTL
  2366 00006AD1 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2367 00006AD2 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2368 00006AD3 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2369 00006AD4 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2370 00006AD5 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2371 00006AD6 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2372                              <1> ;--------------------------------------------------------
  2373                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2374                              <1> ;--------------------------------------------------------
  2375                              <1> MD_TBL2:        
  2376 00006AD7 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2377 00006AD8 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2378 00006AD9 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2379 00006ADA 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2380 00006ADB 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2381 00006ADC 2A                  <1> 	DB	02AH		; GAP LENGTH
  2382 00006ADD FF                  <1> 	DB	0FFH		; DTL
  2383 00006ADE 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2384 00006ADF F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2385 00006AE0 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2386 00006AE1 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2387 00006AE2 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2388 00006AE3 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2389                              <1> ;--------------------------------------------------------
  2390                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2391                              <1> ;--------------------------------------------------------
  2392                              <1> MD_TBL3:
  2393 00006AE4 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2394 00006AE5 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2395 00006AE6 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2396 00006AE7 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2397 00006AE8 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2398 00006AE9 1B                  <1> 	DB	01BH		; GAP LENGTH
  2399 00006AEA FF                  <1> 	DB	0FFH		; DTL
  2400 00006AEB 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2401 00006AEC F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2402 00006AED 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2403 00006AEE 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2404 00006AEF 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2405 00006AF0 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2406                              <1> ;--------------------------------------------------------
  2407                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2408                              <1> ;--------------------------------------------------------
  2409                              <1> MD_TBL4:
  2410 00006AF1 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2411 00006AF2 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2412 00006AF3 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2413 00006AF4 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2414 00006AF5 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2415 00006AF6 2A                  <1> 	DB	02AH		; GAP LENGTH
  2416 00006AF7 FF                  <1> 	DB	0FFH		; DTL
  2417 00006AF8 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2418 00006AF9 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2419 00006AFA 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2420 00006AFB 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2421 00006AFC 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2422 00006AFD 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2423                              <1> ;--------------------------------------------------------
  2424                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2425                              <1> ;--------------------------------------------------------
  2426                              <1> MD_TBL5:
  2427 00006AFE DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2428 00006AFF 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2429 00006B00 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2430 00006B01 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2431 00006B02 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2432 00006B03 2A                  <1> 	DB	02AH		; GAP LENGTH
  2433 00006B04 FF                  <1> 	DB	0FFH		; DTL
  2434 00006B05 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2435 00006B06 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2436 00006B07 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2437 00006B08 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2438 00006B09 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2439 00006B0A 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2440                              <1> ;--------------------------------------------------------
  2441                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2442                              <1> ;--------------------------------------------------------
  2443                              <1> MD_TBL6:
  2444 00006B0B AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2445 00006B0C 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2446 00006B0D 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2447 00006B0E 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2448 00006B0F 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2449 00006B10 1B                  <1> 	DB	01BH		; GAP LENGTH
  2450 00006B11 FF                  <1> 	DB	0FFH		; DTL
  2451 00006B12 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2452 00006B13 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2453 00006B14 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2454 00006B15 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2455 00006B16 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2456 00006B17 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2457                              <1> 
  2458                              <1> 
  2459                              <1> ; << diskette.inc >>
  2460                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2461                              <1> ;
  2462                              <1> ;----------------------------------------
  2463                              <1> ;	ROM BIOS DATA AREAS		:
  2464                              <1> ;----------------------------------------
  2465                              <1> 
  2466                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2467                              <1> 
  2468                              <1> ;----------------------------------------
  2469                              <1> ;	FIXED DISK DATA AREAS		:
  2470                              <1> ;----------------------------------------
  2471                              <1> 
  2472                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2473                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2474                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2475                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2476                              <1> 
  2477                              <1> ;----------------------------------------
  2478                              <1> ;	ADDITIONAL MEDIA DATA		:
  2479                              <1> ;----------------------------------------
  2480                              <1> 
  2481                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2482                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2483                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2484                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2485                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2486                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2487                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2488                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2489                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2490                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2491                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2492                              <1> 
  2493                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2494                              <1> ;
  2495                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2496                              <1> 
  2497                              <1> ERR_TBL:
  2498 00006B18 E0                  <1> 	db	NO_ERR
  2499 00006B19 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2500 00006B1D 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2501                              <1> 
  2502                              <1> ; 17/12/2014 (mov ax, [cfd])
  2503                              <1> ; 11/12/2014
  2504 00006B21 00                  <1> cfd:		db	0		; current floppy drive (for GET_PARM)
  2505                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2506 00006B22 01                  <1> pfd:		db	1		; previous floppy drive (for GET_PARM)
  2507                              <1> 					; (initial value of 'pfd 
  2508                              <1> 					; must be different then 'cfd' value
  2509                              <1> 					; to force updating/initializing
  2510                              <1> 					; current drive parameters) 
  2511 00006B23 90                  <1> align 2
  2512                              <1> 
  2513 00006B24 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2514                              <1> 			      ; (170h)
  2515 00006B26 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2516                              <1> 
  2517                              <1> ; 05/01/2015 
  2518 00006B28 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2519                              <1> 
  2520                              <1> ; *****************************************************************************
  2237                                  ;;;
  2238                                  
  2239 00006B29 90                      Align 2
  2240                                  
  2241                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2242 00006B2A 00                      boot_drv:    db 0  ; boot drive number (physical)
  2243                                  ; 24/11/2014
  2244 00006B2B 00                      drv:	     db 0 
  2245 00006B2C 00                      last_drv:    db 0  ; last hdd
  2246 00006B2D 00                      hdc:         db 0  ; number of hard disk drives
  2247                                  		     ; (present/detected)
  2248                                  ;
  2249                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2250                                  ; Physical drive type & flags
  2251 00006B2E 00                      fd0_type:    db 0  ; floppy drive type
  2252 00006B2F 00                      fd1_type:    db 0    ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2253                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2254                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2255                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2256                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2257 00006B30 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2258 00006B31 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2259 00006B32 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2260 00006B33 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2261                                  		     ; bit 0 - Fixed disk access subset supported
  2262                                  		     ; bit 1 - Drive locking and ejecting
  2263                                  		     ; bit 2 - Enhanced disk drive support
  2264                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2265                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2266                                  		     ; will interpret it as 'LBA ready'!)		
  2267                                  
  2268                                  ; 11/03/2015 - 10/07/2015
  2269 00006B34 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2269 00006B3D 0000000000         
  2270 00006B42 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2270 00006B4B 0000000000         
  2271 00006B50 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2271 00006B59 0000000000         
  2272 00006B5E 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2272 00006B67 000000000000000000-
  2272 00006B70 000000000000000000-
  2272 00006B79 00                 
  2273 00006B7A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2274 00006B81 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2275                                  ;
  2276                                  
  2277                                  ; 27/08/2014
  2278                                  scr_row:
  2279 00006B88 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2280                                  scr_col:
  2281 00006B8C 00000000                	dd 0
  2282                                  
  2283                                  ;; 14/08/2015
  2284                                  ;;msgPM:
  2285                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2286                                  msgKVER:
  2287 00006B90 526574726F20554E49-     	db "Retro UNIX 386 v1.2 - Kernel v0.2.2.0 [31/12/2021]", 0
  2287 00006B99 58203338362076312E-
  2287 00006BA2 32202D204B65726E65-
  2287 00006BAB 6C2076302E322E322E-
  2287 00006BB4 30205B33312F31322F-
  2287 00006BBD 323032315D00       
  2288                                  
  2289 00006BC3 90                      Align 2
  2290                                  
  2291                                  ; 20/08/2014
  2292                                    ; /* This is the default interrupt "handler" :-) */ 
  2293                                    ; Linux v0.12 (head.s)
  2294                                  int_msg:
  2295 00006BC4 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2295 00006BCD 6E7465727275707420-
  2295 00006BD6 212000             
  2296                                  
  2297 00006BD9 90                      Align 2  
  2298                                  
  2299                                  ; 21/08/2014
  2300                                  timer_msg:
  2301 00006BDA 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2301 00006BE3 542032306829202120-
  2301 00006BEC 54696D657220496E74-
  2301 00006BF5 657272757074203A20 
  2302                                  tcountstr:
  2303 00006BFE 303030303020            	db "00000 "
  2304 00006C04 00                      	db 0
  2305                                  
  2306 00006C05 90                      Align 2
  2307                                  	; 21/08/2014
  2308                                  exc_msg:
  2309 00006C06 435055206578636570-     	db "CPU exception ! "
  2309 00006C0F 74696F6E202120     
  2310                                  excnstr: 		; 25/08/2014
  2311 00006C16 3F3F68202045495020-     	db "??h", "  EIP : "
  2311 00006C1F 3A20               
  2312                                  EIPstr: ; 29/08/2014
  2313 00006C21 00<rep Ch>              	times 12 db 0
  2314                                  rtc_msg:
  2315 00006C2D 5265616C2054696D65-     	db "Real Time Clock - "
  2315 00006C36 20436C6F636B202D20 
  2316                                  datestr:
  2317 00006C3F 30302F30302F303030-     	db "00/00/0000"
  2317 00006C48 30                 
  2318 00006C49 20                      	db " "
  2319                                  daystr:
  2320 00006C4A 44415920                	db "DAY "
  2321                                  timestr:	
  2322 00006C4E 30303A30303A3030                db "00:00:00"
  2323 00006C56 20                      	db " "
  2324 00006C57 00                      	db 0 
  2325                                  
  2326                                  daytmp:
  2327                                  	; 28/02/2015
  2328 00006C58 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2328 00006C61 4F4E20545545205745-
  2328 00006C6A 442054485520465249-
  2328 00006C73 2053415420         
  2329                                  
  2330 00006C78 FF                      ptime_seconds: db 0FFh
  2331                                  
  2332                                  	; 23/02/2015
  2333                                  	; 25/08/2014
  2334                                  ;scounter:
  2335                                  ;	db 5
  2336                                  ;	db 19
  2337                                  
  2338                                  ; 28/11/2021
  2339                                  ;; 05/11/2014
  2340                                  ;msg_out_of_memory:
  2341                                  ;	db 	07h, 0Dh, 0Ah
  2342                                  ;	db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2343                                  ; 	db	0Dh, 0Ah, 0
  2344                                  	;
  2345                                  setup_error_msg:
  2346 00006C79 0D0A                    	db 0Dh, 0Ah
  2347 00006C7B 4469736B2053657475-     	db 'Disk Setup Error!' 
  2347 00006C84 70204572726F7221   
  2348 00006C8C 0D0A00                  	db 0Dh, 0Ah,0
  2349                                  
  2350                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2351                                  ;crt_ulc: db 0 ; upper left column (for scroll) 
  2352                                  ;	  db 0 ; upper left row (for scroll)	
  2353                                  
  2354                                  ;crt_lrc: db 79 ; lower right column (for scroll) 
  2355                                  ;	  db 24 ; lower right row (for scroll)
  2356                                  
  2357                                  ; 06/11/2014 (Temporary Data)
  2358                                  ; Memory Information message
  2359                                  ; 14/08/2015
  2360                                  msg_memory_info:
  2361 00006C8F 07                      	db	07h
  2362 00006C90 0D0A                    	db	0Dh, 0Ah
  2363                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2364 00006C92 546F74616C206D656D-     	db	"Total memory : "
  2364 00006C9B 6F7279203A20       
  2365                                  mem_total_b_str: ; 10 digits
  2366 00006CA1 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2366 00006CAA 302062797465730D0A 
  2367 00006CB3 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2367 00006CBC 202020202020202020 
  2368                                  mem_total_p_str: ; 7 digits
  2369 00006CC5 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2369 00006CCE 616765730D0A       
  2370 00006CD4 0D0A                    	db 	0Dh, 0Ah
  2371 00006CD6 46726565206D656D6F-     	db	"Free memory  : "
  2371 00006CDF 727920203A20       
  2372                                  free_mem_b_str:  ; 10 digits
  2373 00006CE5 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2373 00006CEE 3F2062797465730D0A 
  2374 00006CF7 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2374 00006D00 202020202020202020 
  2375                                  free_mem_p_str:  ; 7 digits
  2376 00006D09 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2376 00006D12 616765730D0A       
  2377 00006D18 0D0A00                  	db	0Dh, 0Ah, 0
  2378                                  
  2379                                  dsk_ready_msg:
  2380 00006D1B 0D0A                    	db 	0Dh, 0Ah
  2381                                  dsktype:
  2382 00006D1D 6664                    	db	'fd'
  2383                                  dskx:
  2384 00006D1F 30                      	db	'0'
  2385 00006D20 20                      	db	20h
  2386 00006D21 697320524541445920-     	db 	'is READY ...'
  2386 00006D2A 2E2E2E             
  2387 00006D2D 00                      	db 	0
  2388                                  nextline:
  2389 00006D2E 0D0A00                  	db 	0Dh, 0Ah, 0
  2390                                  
  2391                                  ; KERNEL - SYSINIT Messages
  2392                                  ; 24/08/2015
  2393                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2394                                  ; 14/07/2013
  2395                                  ;kernel_init_err_msg:
  2396                                  ;	db 0Dh, 0Ah
  2397                                  ;	db 07h
  2398                                  ;	db 'Kernel initialization ERROR !'
  2399                                  ;	db 0Dh, 0Ah, 0 
  2400                                  ; 24/08/2015
  2401                                  ;;; (temporary kernel init message has been removed
  2402                                  ;;;  from 'sys_init' code)
  2403                                  ;kernel_init_ok_msg: 
  2404                                  ;	db 0Dh, 0Ah
  2405                                  ;	db 07h
  2406                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2407                                  ;	db 0Dh, 0Ah
  2408                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2409                                  ;	db 0Dh, 0Ah, 0
  2410                                  panic_msg:
  2411 00006D31 0D0A07                  	db 0Dh, 0Ah, 07h
  2412 00006D34 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2412 00006D3D 726E656C2050616E69-
  2412 00006D46 632021             
  2413 00006D49 0D0A00                  	db 0Dh, 0Ah, 0
  2414                                  etc_init_err_msg:
  2415 00006D4C 0D0A                    	db 0Dh, 0Ah
  2416 00006D4E 07                      	db 07h
  2417 00006D4F 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2417 00006D58 74632F696E69742021-
  2417 00006D61 3F                 
  2418 00006D62 0D0A00                  	db 0Dh, 0Ah, 0
  2419                                  
  2420                                  ; 10/05/2015
  2421                                  badsys_msg:
  2422 00006D65 0D0A                    	db 0Dh, 0Ah
  2423 00006D67 07                      	db 07h
  2424 00006D68 496E76616C69642053-     	db 'Invalid System Call !'
  2424 00006D71 797374656D2043616C-
  2424 00006D7A 6C2021             
  2425 00006D7D 0D0A                    	db 0Dh, 0Ah
  2426 00006D7F 4541583A20              	db 'EAX: '
  2427                                  bsys_msg_eax:
  2428 00006D84 303030303030303068      	db '00000000h'
  2429 00006D8D 0D0A                    	db 0Dh, 0Ah
  2430 00006D8F 4549503A20              	db 'EIP: '
  2431                                  bsys_msg_eip:
  2432 00006D94 303030303030303068      	db '00000000h' 
  2433 00006D9D 0D0A00                  	db 0Dh, 0Ah, 0
  2434                                  
  2435                                  BSYS_M_SIZE equ $ - badsys_msg
  2436                                  
  2437                                  align 2
  2438                                  
  2439                                  ; EPOCH Variables
  2440                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2441                                  ; 09/04/2013 epoch variables
  2442                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2443                                  ;
  2444 00006DA0 B207                    year: 	dw 1970
  2445 00006DA2 0100                    month: 	dw 1
  2446 00006DA4 0100                    day: 	dw 1
  2447 00006DA6 0000                    hour: 	dw 0
  2448 00006DA8 0000                    minute: dw 0
  2449 00006DAA 0000                    second: dw 0
  2450                                  
  2451                                  DMonth:
  2452 00006DAC 0000                    	dw 0
  2453 00006DAE 1F00                    	dw 31
  2454 00006DB0 3B00                    	dw 59
  2455 00006DB2 5A00                    	dw 90
  2456 00006DB4 7800                    	dw 120
  2457 00006DB6 9700                    	dw 151
  2458 00006DB8 B500                    	dw 181
  2459 00006DBA D400                    	dw 212
  2460 00006DBC F300                    	dw 243
  2461 00006DBE 1101                    	dw 273
  2462 00006DC0 3001                    	dw 304
  2463 00006DC2 4E01                    	dw 334
  2464                                  
  2465                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2466 00006DC4 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2467                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2468 00006DC6 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2469                                  		   ;   between 16 MB and 4 GB.
  2470 00006DC8 90<rep 8h>              align 16
  2471                                  
  2472                                  bss_start:
  2473                                  
  2474                                  ABSOLUTE bss_start
  2475                                  
  2476                                  	; 11/03/2015
  2477                                  	; Interrupt Descriptor Table (20/08/2014)
  2478                                  idt:
  2479 00006DD0 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2480                                  idt_end:
  2481                                  
  2482                                  ;alignb 4
  2483                                  
  2484                                  task_state_segment:
  2485                                  	; 24/03/2015
  2486 00006FD0 ????                    tss.link:   resw 1
  2487 00006FD2 ????                    	    resw 1
  2488                                  ; tss offset 4	
  2489 00006FD4 ????????                tss.esp0:   resd 1
  2490 00006FD8 ????                    tss.ss0:    resw 1
  2491 00006FDA ????                    	    resw 1	
  2492 00006FDC ????????                tss.esp1:   resd 1
  2493 00006FE0 ????                    tss.ss1:    resw 1
  2494 00006FE2 ????                    	    resw 1 	
  2495 00006FE4 ????????                tss.esp2:   resd 1
  2496 00006FE8 ????                    tss.ss2:    resw 1
  2497 00006FEA ????                    	    resw 1
  2498                                  ; tss offset 28
  2499 00006FEC ????????                tss.CR3:    resd 1
  2500 00006FF0 ????????                tss.eip:    resd 1
  2501 00006FF4 ????????                tss.eflags: resd 1
  2502                                  ; tss offset 40
  2503 00006FF8 ????????                tss.eax:    resd 1		 		
  2504 00006FFC ????????                tss.ecx:    resd 1
  2505 00007000 ????????                tss.edx:    resd 1
  2506 00007004 ????????                tss.ebx:    resd 1
  2507 00007008 ????????                tss.esp:    resd 1
  2508 0000700C ????????                tss.ebp:    resd 1
  2509 00007010 ????????                tss.esi:    resd 1
  2510 00007014 ????????                tss.edi:    resd 1
  2511                                  ; tss offset 72
  2512 00007018 ????                    tss.ES:     resw 1
  2513 0000701A ????                    	    resw 1	
  2514 0000701C ????                    tss.CS:	    resw 1
  2515 0000701E ????                    	    resw 1
  2516 00007020 ????                    tss.SS:	    resw 1
  2517 00007022 ????                    	    resw 1
  2518 00007024 ????                    tss.DS:	    resw 1
  2519 00007026 ????                    	    resw 1
  2520 00007028 ????                    tss.FS:	    resw 1
  2521 0000702A ????                    	    resw 1
  2522 0000702C ????                    tss.GS:	    resw 1
  2523 0000702E ????                    	    resw 1		
  2524 00007030 ????                    tss.LDTR:   resw 1
  2525 00007032 ????                    	    resw 1
  2526                                  ; tss offset 100		
  2527 00007034 ????                    	    resw 1		
  2528 00007036 ????                    tss.IOPB:   resw 1
  2529                                  ; tss offset 104 
  2530                                  tss_end:
  2531                                  
  2532 00007038 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2533                                  		    ;  (Physical address = Virtual address)	 	
  2534 0000703C ????????                memory_size: resd 1 ; memory size in pages
  2535 00007040 ????????                free_pages:  resd 1 ; number of free pages		
  2536 00007044 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2537                                  		    ;   first free page search
  2538 00007048 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2539                                  		    ;   next free page search will be
  2540                                  		    ;   stopped after it. (end of M.A.T.)
  2541 0000704C ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2542                                  		    ; first free page search
  2543                                  		    ;   will be started on it. (for user)
  2544 00007050 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2545                                  
  2546                                  ;;;
  2547                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2548                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2549 00007054 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2550                                  			  ; NOTE: active page only
  2551 00007056 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2552                                  active_page: 
  2553 00007066 ??                      ptty: 	     resb 1 	  ; current tty
  2554                                  ; 01/07/2015
  2555 00007067 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2556                                  ; 26/10/2015
  2557                                  ; 07/09/2014
  2558 00007068 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2559                                  
  2560                                  ; 21/08/2014
  2561 0000707C ????????                tcount:	     resd 1
  2562                                  
  2563                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2564 00007080 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2565                                  
  2566                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2567                                  ; (open mode locks for pseudo TTYs)
  2568                                  ; [ major tty locks (return error in any conflicts) ]
  2569 00007084 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2570                                  
  2571                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2572                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2573 00007098 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2574                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2575                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2576                                  ;; 0 means serial port is not available 
  2577                                  ;;comprm: ; 25/06/2014
  2578 000070A2 ??                      com1p:       resb 1  ;;0E3h
  2579 000070A3 ??                      com2p:       resb 1  ;;0E3h
  2580                                  
  2581                                  ; 17/11/2015
  2582                                  ; request for response (from the terminal)	
  2583 000070A4 ????                    req_resp:    resw 1 			
  2584                                  ; 07/11/2015
  2585 000070A6 ??                      ccomport:    resb 1 ; current COM (serial) port
  2586                                  		    ; (0= COM1, 1= COM2)
  2587                                  ; 09/11/2015
  2588 000070A7 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2589                                  ; 07/11/2015
  2590 000070A8 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2591 000070AA ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2592                                  
  2593                                  ; 23/10/2015
  2594                                  ; SERIAL PORTS - COMMUNICATION MODES
  2595                                  ; (Retro UNIX 386 v1 feature only!)
  2596                                  ; 0 - command mode (default/initial mode)
  2597                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2598                                  ;;; communication modes for futre versions:  
  2599                                  ; // 2 - keyboard mode (ascii+scancode input)
  2600                                  ; // 3 - mouse mode
  2601                                  ; // 4 - device control (output) mode
  2602                                  ; VALID COMMANDS for current version:
  2603                                  ; 	'LOGIN'
  2604                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2605                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2606                                  ;  Login response: db 0FFh, 'login', 0
  2607                                  ;	 ("login request accepted, wait for login prompt") 
  2608                                  ; When a login requests is received and acknowledged (by
  2609                                  ; serial port interrupt handler (communication procedure),
  2610                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2611                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2612                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2613                                  ; 
  2614                                  ; 'sys connect' system call is used to change communication mode
  2615                                  ; except 'LOGIN' command which is used to start terminal mode
  2616                                  ; by using (COM port) terminal.
  2617                                  
  2618                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2619                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2620                                  ;com1mode:    resb 1 ; communication mode for COM1
  2621                                  ;com1com:     resb 1 ; communication command for COM1
  2622                                  ;com2mode:    resb 1 ; communication mode for COM1
  2623                                  ;com2com      resb 1 ; communication command for COM1
  2624                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2625                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2626                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2627                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2628                                  
  2629                                  ; 22/08/2014 (RTC)
  2630                                  ; (Packed BCD)
  2631 000070AC ??                      time_seconds: resb 1
  2632 000070AD ??                      time_minutes: resb 1
  2633 000070AE ??                      time_hours:   resb 1
  2634 000070AF ??                      date_wday:    resb 1
  2635 000070B0 ??                      date_day:     resb 1
  2636 000070B1 ??                      date_month:   resb 1			
  2637 000070B2 ??                      date_year:    resb 1
  2638 000070B3 ??                      date_century: resb 1
  2639                                  
  2640                                  %include 'diskbss.s'	; UNINITIALIZED DISK (BIOS) DATA
  2641                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2642                              <1> ; Last Modification: 10/07/2015
  2643                              <1> ;	(Unitialized Disk Parameters Data section for 'DISKIO.INC') 
  2644                              <1> ;
  2645                              <1> ; *****************************************************************************
  2646                              <1> 
  2647                              <1> alignb 2
  2648                              <1> 
  2649                              <1> ;----------------------------------------
  2650                              <1> ;	TIMER DATA AREA 		:
  2651                              <1> ;----------------------------------------
  2652                              <1> 
  2653                              <1> TIMER_LH:	; 16/02/2015
  2654 000070B4 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2655 000070B6 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2656 000070B8 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2657                              <1> 
  2658                              <1> ;----------------------------------------
  2659                              <1> ;	DISKETTE DATA AREAS		:
  2660                              <1> ;----------------------------------------
  2661                              <1> 
  2662 000070B9 ??                  <1> SEEK_STATUS:	resb	1
  2663 000070BA ??                  <1> MOTOR_STATUS:	resb	1
  2664 000070BB ??                  <1> MOTOR_COUNT:	resb	1
  2665 000070BC ??                  <1> DSKETTE_STATUS:	resb	1
  2666 000070BD ??????????????      <1> NEC_STATUS:	resb	7
  2667                              <1> 
  2668                              <1> ;----------------------------------------
  2669                              <1> ;	ADDITIONAL MEDIA DATA		:
  2670                              <1> ;----------------------------------------
  2671                              <1> 
  2672 000070C4 ??                  <1> LASTRATE:	resb 	1
  2673 000070C5 ??                  <1> HF_STATUS:	resb 	1
  2674 000070C6 ??                  <1> HF_ERROR:	resb 	1
  2675 000070C7 ??                  <1> HF_INT_FLAG:	resb 	1
  2676 000070C8 ??                  <1> HF_CNTRL:	resb 	1
  2677 000070C9 ????????            <1> DSK_STATE:	resb 	4
  2678 000070CD ????                <1> DSK_TRK:	resb 	2
  2679                              <1> 
  2680                              <1> ;----------------------------------------
  2681                              <1> ;	FIXED DISK DATA AREAS		:
  2682                              <1> ;----------------------------------------
  2683                              <1> 
  2684 000070CF ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2685 000070D0 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2686 000070D1 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2687                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2688                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2689                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2690                              <1> 
  2691 000070D2 ????                <1> alignb 4
  2692                              <1> 
  2693                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2694                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2695                              <1> HF_TBL_VEC: ; 22/12/2014	
  2696 000070D4 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2697 000070D8 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2698 000070DC ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2699 000070E0 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2700                              <1> 
  2701                              <1> ; 03/01/2015
  2702 000070E4 ??                  <1> LBAMode:     	resb	1
  2703                              <1> 
  2704                              <1> ; *****************************************************************************
  2641                                  
  2642                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2643                                  
  2644                                  ;alignb 2
  2645                                  
  2646                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2647                              <1> ; Temporary Runix kernel v2.0 file for debug - 22/11/2021
  2648                              <1> ; (re-write kernel for test by using previous version without a major defect)
  2649                              <1> ; ****************************************************************************
  2650                              <1> ; Retro UNIX 386 v1.2 Kernel - ux.s
  2651                              <1> ; Last Modification: 31/12/2021
  2652                              <1> ;
  2653                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2654                              <1> ; (Modified from 
  2655                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2656                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2657                              <1> ; ----------------------------------------------------------------------------
  2658                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2659                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2660                              <1> ; <Bell Laboratories (17/3/1972)>
  2661                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2662                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2663                              <1> ; ****************************************************************************
  2664                              <1> 
  2665                              <1> ; 22/11/2021 (Modification in Runix v1.1 'ux.s' for runix v2 fs compatibility)
  2666                              <1> ; 18/07/2021
  2667                              <1> ; 15/07/2021
  2668                              <1> ; 12/05/2021
  2669                              <1> ; 09/05/2021
  2670                              <1> ; 06/05/2021
  2671                              <1> ; 02/05/2021
  2672                              <1> ; 26/01/2020 (NASM version of SuperBlock structure in UNIXHDCP.ASM)
  2673                              <1> 
  2674                              <1> ; 21/12/2019 (UNIXCOPY.COM, UNIXCOPY.ASM, UNIXHDCP.COM, UNIXHDCP.ASM)
  2675                              <1> ; 19/12/2019 (UNIXHDFS.COM, RUFSHDI.ASM)
  2676                              <1> ; 01/09/2019 - Retro UNIX 386 v2 SuperBlock
  2677                              <1> 
  2678                              <1> ; 14/01/2020 - Super Block modification:
  2679                              <1> ;	     - Extended sections/divisions (consequental sectors)
  2680                              <1> ;	     - (for swapping, configuration, boot space etc.)	
  2681                              <1> 
  2682                              <1> struc SB ; SuperBlock
  2683                              <1> 
  2684 00000000 ????????            <1> .Header:	resd 1
  2685                              <1> ;.HiddenSects:
  2686 00000004 ????????            <1> .BootSectAddr:	resd 1	; Hidden Sectors
  2687                              <1> ;.TotalSects:
  2688 00000008 ????????            <1> .VolumeSize:	resd 1	; Entire Volume/Partition Size (includes ext. volume)	
  2689 0000000C ????????            <1> .Version:	resd 1	
  2690 00000010 ????????            <1> .BlockSize:	resd 1	
  2691 00000014 ????????            <1> .InodeCount:	resd 1		
  2692 00000018 ????????            <1> .FreeMapAddr:	resd 1	
  2693 0000001C ????????            <1> .FreeMapSize:	resd 1	
  2694 00000020 ????????            <1> .InodeMapAddr:	resd 1	
  2695 00000024 ????????            <1> .InodeMapSize:	resd 1	
  2696 00000028 ????????            <1> .InodeTblAddr:	resd 1	
  2697 0000002C ????????            <1> .InodeTblSize:	resd 1	
  2698 00000030 ????????            <1> .FreeInodes:	resd 1	
  2699 00000034 ????????            <1> .FirstFreeIno:	resd 1	
  2700 00000038 ????????            <1> .FreeBlocks:	resd 1	
  2701 0000003C ????????            <1> .FirstFreeBlk:	resd 1	
  2702 00000040 <res 13h>           <1> .BootSecParms:	resb 19	; v1
  2703 00000053 ??????????          <1> .BSExtension:	resb 5	; v2 HDFS
  2704 00000058 ??                  <1> .Status:	resb 1	; 12/05/2021 (system modification status) (*)
  2705 00000059 ??                  <1> .Pdrv:		resb 1  ; Physical disk number (index) ; 12/05/2021 (*) 
  2706 0000005A ????                <1> .Uno:		resw 1	; user/process number ; 12/05/2021 (*)
  2707 0000005C ????????            <1> .ModifTime:	resd 1	; (last) modification time (*)
  2708 00000060 ????????            <1> .ExtdVolTbl:	resd 1	; Extended Volume Start/Table Address
  2709 00000064 ????????            <1> .ExtdVolSize:	resd 1	; Extended Volume (swap section etc.) Size	
  2710 00000068 ??                  <1> .LBA_rw:	resb 1
  2711 00000069 ??                  <1> .ClusterSize:	resb 1
  2712 0000006A ??                  <1> .ReadOnly:	resb 1	; (SB will not be written to disk if bit 0 is 1)
  2713 0000006B ??                  <1> .Mounted:	resb 1
  2714 0000006C ????????            <1> .MountInode:	resd 1  ; double word
  2715 00000070 ??                  <1> .DevMajor:	resb 1
  2716 00000071 ??                  <1> .DevMinor:	resb 1
  2717 00000072 ??                  <1> .LongName:	resb 1
  2718 00000073 ??                  <1> .Direntry32:	resb 1
  2719                              <1> ; 18/07/2021
  2720 00000074 ????????            <1> .FileBuffer:	resd 1
  2721 00000078 ????????            <1> .ItabBuffer:	resd 1
  2722 0000007C ????????            <1> .ImapBuffer:	resd 1
  2723 00000080 ????????            <1> .FmapBuffer:	resd 1
  2724                              <1>  ; 15/07/2021
  2725 00000084 ????????            <1> .LastInode:	resd 1
  2726                              <1> ; 02/05/2021
  2727 00000088 ????????            <1> .FmapIndex:	resd 1
  2728 0000008C ????????            <1> .ImapIndex:	resd 1
  2729 00000090 ????????            <1> .ItableIndex:	resd 1
  2730 00000094 <res 168h>          <1> .Reserved:	resb 508-148 ; 18/07/2021
  2731 000001FC ????????            <1> .Footer:	resd 1
  2732                              <1> 
  2733                              <1> endstruc
  2734                              <1> 
  2735                              <1> ; 26/01/2020 (unix386.s, ux.s)
  2736                              <1> ; 14/01/2020
  2737                              <1> SB.HiddenSects	equ SB.BootSectAddr
  2738                              <1> SB.TotalSects	equ SB.VolumeSize
  2739                              <1> 
  2740                              <1> ; 11/05/2021 (Retro UNIX 386 v2)
  2741                              <1> ; Super block status byte (byte 0 of SB.status dword)
  2742                              <1> ; 	bit 0 - superblock modified flag
  2743                              <1> ; 	bit 1 - inode map modified flag
  2744                              <1> ; 	bit 2 - free blocks map modified flag
  2745                              <1> ; 	bit 3 - inode table modified flag
  2746                              <1> ;; 	bit 4 - boot sector modified flag ; 17/08/2021
  2747                              <1> ; 17/08/2021
  2748                              <1> ;	bit 4 - file data write error (for SB.LastInode)
  2749                              <1> ;	bit 5 - inode table write error (for SB.LastInode)
  2750                              <1> ;	bit 6 - inode map write error (for SB.LastInode)
  2751                              <1> ;	bit 7 - free blocks map write error (for SB.LastInode)
  2752                              <1> 	
  2753                              <1> ; 21/12/2019
  2754                              <1> ; 19/12/2019 - Retro UNIX 386 v2 HD (071h) partition boot sector 
  2755                              <1> ;	       (UNIXHDFS.ASM)
  2756                              <1> ; 04/12/2015 (14 byte file names - Retro UNIX 386 v1.1)
  2757                              <1> ; 14/07/2015 (8 byte file names - Retro UNIX 8086 v1 & Retro UNIX 386 v1.0)
  2758                              <1> 
  2759                              <1> bsFSystemID 	equ 2  ; db 'RUFS'	
  2760                              <1> bsVolumeSerial 	equ 6  ; dd 0 ; (4 bytes)
  2761                              <1> bsFDSign	equ 10 ; db 'fd'
  2762                              <1> bsDriveNumber 	equ 12 ; db 0 ; fd0 or fd1 (0 or 1)
  2763                              <1> bsReserved 	equ 13 ; db 0 ; (512 bytes per sector)	
  2764                              <1> bsSecPerTrack	equ 14 ; db 18 ; (9 or 15)	
  2765                              <1> bsHeads		equ 15 ; db  ; 2
  2766                              <1> bsTracks	equ 16 ; dw 80 ; bsCylinders
  2767                              <1> bs_bf_inode_number equ 18 ; dw 0 ; 0 or Boot/Startup File I-Number
  2768                              <1> bsInfoEndsign	equ 20 ; db '@'
  2769                              <1> ; 21/12/2019
  2770                              <1> bsMagic		equ 20 ; db '@'
  2771                              <1> bsPartitionID	equ 21 ; db 0 ; db 71h
  2772                              <1> bsHiddenSects	equ 22 ; dd 0 ; Hidden sectors (Boot Sector LBA)
  2773                              <1> 
  2774                              <1> ; 22/11/2021 - Retro UNIX v2 I-node Flags
  2775                              <1> ; ------------------------------------------------------------------
  2776                              <1> ; UINSTALL.ASM (included in UNIXFDFS.ASM) - 23/01/2020
  2777                              <1> ; ------------------------------------------------------------------
  2778                              <1> 
  2779                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for files
  2780                              <1> ; 1000000000000000b 	IFREG - 1 = regular file (8000h)
  2781                              <1> ; 0100000000000000b	IFDIR - 1 = directory (4000h)
  2782                              <1> ; 0010000000000000b	IRSVD - 0 = reserved bit (2000h) ; Mounted flag
  2783                              <1> ; 0001000000000000b	ILARG - large file addressing bit (1000h)
  2784                              <1> ; 0000100000000000b	ISUID - set user id on exec (800h)
  2785                              <1> ; 0000010000000000b	ISGID - set group id on exec (400h)
  2786                              <1> ; 0000001000000000b	IEXTT - 1 = use extents (200h)
  2787                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2788                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2789                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2790                              <1> ; 0000000000100000b	read, group (20h)
  2791                              <1> ; 0000000000010000b	write, group (10h)
  2792                              <1> ; 0000000000001000b	execute, group (08h)
  2793                              <1> ; 0000000000000100b	read, others (04h)
  2794                              <1> ; 0000000000000010b	write, others (02h)
  2795                              <1> ; 0000000000000001b	execute, others (01h)
  2796                              <1> 
  2797                              <1> ; Retro UNIX 386 v2 I-node Flags: (di_mode) for devices
  2798                              <1> ; 1000000000000000b 	IFREG - 0 = device file (8000h)
  2799                              <1> ; 0100000000000000b	IFBLK - 1 = block device (4000h)
  2800                              <1> ; 0010000000000000b	IFCHR - character special (2000h) -always 1-
  2801                              <1> ; 0001000000000000b	IFIFO - fifo special (1000h)
  2802                              <1> ; 0000100000000000b	IPIPE - pipe special (800h) ; 07/02/2020
  2803                              <1> ; 0000010000000000b	IREDIR - redirected (400h)  ; 07/02/2020
  2804                              <1> ; 0000001000000000b	IEXTR - 1 = external device driver (200h)
  2805                              <1> ; 0000000100000000b	IREAD - read, owner (100h)
  2806                              <1> ; 0000000010000000b	IWRITE - write, owner (80h)
  2807                              <1> ; 0000000001000000b	IEXEC - execute, owner (40h)
  2808                              <1> ; 0000000000100000b	read, group (20h)
  2809                              <1> ; 0000000000010000b	write, group (10h)
  2810                              <1> ; 0000000000001000b	execute, group (08h)
  2811                              <1> ; 0000000000000100b	read, others (04h)
  2812                              <1> ; 0000000000000010b	write, others (02h)
  2813                              <1> ; 0000000000000001b	execute, others (01h)
  2814                              <1> 
  2815                              <1> alignb 2
  2816                              <1> 
  2817                              <1> inode:
  2818                              <1> 	;; 11/03/2013. 
  2819                              <1> 	;;Derived from UNIX v1 source code 'inode' structure (ux).
  2820                              <1> 	;;i.
  2821                              <1> 	;
  2822                              <1> 	;i.flgs: resw 1
  2823                              <1> 	;i.nlks: resb 1
  2824                              <1> 	;i.uid:	 resb 1
  2825                              <1>         ;i.size: resw 1 ; size
  2826                              <1> 	;i.dskp: resw 8 ; 16 bytes
  2827                              <1> 	;i.ctim: resd 1
  2828                              <1> 	;i.mtim: resd 1
  2829                              <1> 	;i.rsvd: resw 1 ; Reserved (ZERO/Undefined word for UNIX v1)
  2830                              <1> 
  2831                              <1> 	; 26/01/2020
  2832                              <1> 	; Retro UNIX 386 v2.0 - Modified UNIX v7 inode model
  2833                              <1> 	;	(15/09/2029 .. 18/12/2019)
  2834                              <1> 
  2835 00006DD0 ????                <1> 	i.flgs:   resw 1	; /* mode and type of file */
  2836 00006DD2 ????                <1> 	i.nlks:	  resw 1	; /* number of links to file */
  2837 00006DD4 ????                <1> 	i.uid:	  resw 1	; /* owner's user id */  - 0 to 655535 -
  2838 00006DD6 ??                  <1> 	i.gid:	  resb 1	; /* owner's group id */ - o to 255 -
  2839 00006DD7 ??                  <1> 	i.size_h: resb 1	; /* number of bytes in file */ ; byte 5
  2840 00006DD8 ????????            <1> 	i.size:	  resd 1 ; size	; /* number of bytes in file */
  2841 00006DDC <res 28h>           <1> 	i.dskp:	  resd 10 ; 40 bytes ; /* disk block addresses */
  2842 00006E04 ????????            <1> 	i.atim:	  resd 1	; /* time last accessed */
  2843 00006E08 ????????            <1> 	i.mtim:	  resd 1	; /* time last modified */
  2844 00006E0C ????????            <1> 	i.ctim:	  resd 1	; /* time created */
  2845                              <1> 
  2846                              <1> I_SIZE	equ $ - inode
  2847                              <1> 
  2848                              <1> process:
  2849                              <1> 	; 06/05/2015
  2850                              <1> 	; 11/03/2013 - 05/02/2014
  2851                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2852                              <1> 	;p.
  2853                              <1> 	
  2854 00006E10 <res 20h>           <1>         p.pid:   resw nproc
  2855 00006E30 <res 20h>           <1>         p.ppid:  resw nproc
  2856 00006E50 <res 20h>           <1>         p.break: resw nproc
  2857 00006E70 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2858 00006E80 <res 10h>           <1> 	p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2859 00006E90 <res 10h>           <1> 	p.link:	 resb nproc
  2860 00006EA0 <res 10h>           <1> 	p.stat:	 resb nproc
  2861                              <1> 
  2862                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2863 00006EB0 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2864                              <1> 			    ; 'user' structure	
  2865                              <1> 
  2866                              <1> P_SIZE	equ $ - process
  2867                              <1> 
  2868                              <1> ; fsp table (original UNIX v1)
  2869                              <1> ;
  2870                              <1> ;Entry
  2871                              <1> ;          15                                      0
  2872                              <1> ;  1     |---|---------------------------------------|
  2873                              <1> ;        |r/w|       i-number of open file           |
  2874                              <1> ;        |---|---------------------------------------| 
  2875                              <1> ;        |               device number               |
  2876                              <1> ;        |-------------------------------------------|
  2877                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2878                              <1> ;        |-------------------------------------------| 
  2879                              <1> ;        |  flag that says    | number of processes  |
  2880                              <1> ;        |   file deleted     | that have file open  |
  2881                              <1> ;        |-------------------------------------------| 
  2882                              <1> ;  2     |                                           |
  2883                              <1> ;        |-------------------------------------------| 
  2884                              <1> ;        |                                           |
  2885                              <1> ;        |-------------------------------------------|
  2886                              <1> ;        |                                           |
  2887                              <1> ;        |-------------------------------------------|
  2888                              <1> ;        |                                           |
  2889                              <1> ;        |-------------------------------------------| 
  2890                              <1> ;  3     |                                           | 
  2891                              <1> ;        |                                           |  
  2892                              <1> ;
  2893                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2894                              <1> 
  2895                              <1> ; 27/03/2020 - Retro UNIX 386 v2 - FSP (OPEN FILES) TABLE 
  2896                              <1> 
  2897                              <1> ;Entry
  2898                              <1> ;         15                    7                   0
  2899                              <1> ;  1     |-------------------------------------------|
  2900                              <1> ;        |   	     i-number of open file           |
  2901                              <1> ;        |-------------------------------------------| 
  2902                              <1> ;        |        high word of 32 bit i-number       |
  2903                              <1> ;        |-------------------------------------------|
  2904                              <1> ;        | open mode & status  |   device number     |
  2905                              <1> ;        |-------------------------------------------|
  2906                              <1> ;        |    reserved byte    |     open count      |
  2907                              <1> ;        |-------------------------------------------| 
  2908                              <1> ;        | offset pointer, i.e., r/w pointer to file |
  2909                              <1> ;        |-------------------------------------------|
  2910                              <1> ;        |   64 bit file offset pointer (bit 16-31)  | 
  2911                              <1> ;        |-------------------------------------------|
  2912                              <1> ;        |   64 bit file offset pointer (bit 32-47)  | 
  2913                              <1> ;        |-------------------------------------------|
  2914                              <1> ;        |   64 bit file offset pointer (bit 48-63)  | 
  2915                              <1> ;        |-------------------------------------------|
  2916                              <1> ;  2     |                                           |
  2917                              <1> ;        |-------------------------------------------| 
  2918                              <1> ;        |                                           |
  2919                              <1> ;        |-------------------------------------------|
  2920                              <1> ;        |                                           |
  2921                              <1> ;        |-------------------------------------------|
  2922                              <1> ;        |                                           |
  2923                              <1> ;        |-------------------------------------------| 
  2924                              <1> ;        |                                           | 
  2925                              <1> 
  2926                              <1> ; 22/11/2021
  2927                              <1> ; 21/07/2021 - Retro UNIX 386 v2 open file struc revision
  2928                              <1> 
  2929                              <1> struc file	; open files (fsp) structure
  2930 00000000 ????                <1>   .inode:  resw 1  ; inode number of open file (32 bit)
  2931 00000002 ????                <1>   .i32:	   resw 1  ; higher word of inode number (reserved)
  2932 00000004 ??                  <1>   .drive:  resb 1  ; logical drive (disk) number
  2933 00000005 ??                  <1>   .flags:  resb 1  ; open mode and status
  2934 00000006 ??                  <1>   .count:  resb 1  ; number of processes that have file open
  2935                              <1>   ;.rsvd:  resb 1  ; reserved byte (for next versions)
  2936 00000007 ??                  <1>   .mnt:    resb 1  ; mnttab index+1 (0 = not mounted)
  2937 00000008 ????????            <1>   .offset: resd 1  ; file offset/pointer (64 bit) 
  2938 0000000C ????????            <1>   .o64:	   resd 1  ; higher 32 bit of file offset
  2939                              <1>  .size:  ; = 16		
  2940                              <1> endstruc
  2941                              <1> 
  2942                              <1> ; 22/11/2021
  2943                              <1> fp.size equ file.size
  2944                              <1> 
  2945                              <1> ; 22/11/2021 (16/05/2021)
  2946 00006DD0 <res 320h>          <1> fsp:	resb (NFILES*fp.size) ; NFILES * 16
  2947                              <1> ; 15/04/2015
  2948                              <1> ;fsp:	resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2949 000070F0 <res 20h>           <1> bufp:	resd (nbuf+2) ; will be initialized 
  2950 00007110 ????????            <1> ii:	resd 1 ; 22/11/2021 ; 32 bit inode number (high word is 0)
  2951                              <1> ; 22/11/2021
  2952 00007114 ??                  <1> idev:	resb 1 ; logical drive number of current inode, [ii]
  2953 00007115 ??                  <1> cdev:	resb 1 ; current logical drive number for current user
  2954                              <1> 
  2955                              <1> ; 18/05/2015
  2956                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2957                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2958                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2959                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2960                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2961                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2962                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2963                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2964                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2965                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2966                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2967 00007116 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2968                              <1> 	        ; as above, for physical drives numbers in following table
  2969 00007117 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2970                              <1> ; 15/04/2015
  2971 00007118 ??                  <1> active:	 resb 1 
  2972 00007119 ??                  <1> 	 resb 1 ; 09/06/2015
  2973 0000711A ????                <1> mpid:	 resw 1
  2974                              <1> ; 22/11/2021 (32 bit inode numbers)
  2975 0000711C ????????            <1> rootdir: resd 1
  2976 00007120 ????????            <1> mnti:	 resd 1
  2977                              <1> 
  2978                              <1> ; 14/02/2014
  2979                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2980                              <1> ;		      Single level run queue
  2981                              <1> ;		      (in order to solve sleep/wakeup lock)
  2982 00007124 ????                <1> runq:	 resw 1
  2983 00007126 ??                  <1> imod:	 resb 1
  2984 00007127 ??                  <1> smod:	 resb 1
  2985 00007128 ??                  <1> mmod:	 resb 1
  2986 00007129 ??                  <1> sysflg:	 resb 1
  2987                              <1> 
  2988 0000712A ????                <1> alignb 4
  2989                              <1> 
  2990                              <1> user:
  2991                              <1> 	; 04/12/2021 - Retro UNIX 386 v1.2
  2992                              <1> 	; 24/10/2021
  2993                              <1> 	; 18/10/2021
  2994                              <1> 	; 10/06/2021
  2995                              <1> 	; 30/05/2021
  2996                              <1> 	; 29/05/2021
  2997                              <1> 	; 21/05/2021
  2998                              <1> 	; 20/05/2021
  2999                              <1> 	; 16/05/2021
  3000                              <1> 	; 01/05/2021
  3001                              <1> 	; 27/03/2021
  3002                              <1> 	; 17/04/2020, 28/04/2020
  3003                              <1> 	; 25/03/2020, 28/03/2020
  3004                              <1> 	; 20/03/2020, 22/03/2020, 23/03/2020
  3005                              <1> 	; 05/03/2020, 08/03/2020, 14/03/2020
  3006                              <1> 	; 07/02/2020 - Retro UNIX 386 v2
  3007                              <1> 	;
  3008                              <1> 	; 27/02/2017 - TRDOS 386
  3009                              <1> 	; 13/01/2017 - TRDOS 386
  3010                              <1> 	; 10/01/2017 - TRDOS 386
  3011                              <1> 	; 19/12/2016 - TRDOS 386	
  3012                              <1> 	; 21/05/2016 - TRDOS 386 (TRDOS v2.0) 
  3013                              <1> 	; 	       [u.pri] usage method modification
  3014                              <1> 	;
  3015                              <1> 	; 04/12/2015 - Retro UNIX 386 v1.1 (14 byte file/directory names)
  3016                              <1> 	; 18/10/2015
  3017                              <1> 	; 12/10/2015
  3018                              <1> 	; 21/09/2015
  3019                              <1> 	; 24/07/2015
  3020                              <1> 	; 16/06/2015
  3021                              <1> 	; 09/06/2015
  3022                              <1> 	; 11/05/2015
  3023                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  3024                              <1> 	; 10/10/2013
  3025                              <1> 	; 11/03/2013. 
  3026                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  3027                              <1> 	;u.
  3028                              <1> 
  3029 0000712C ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  3030 00007130 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  3031 00007134 ????????            <1> 	u.r0:	  resd 1 ; eax
  3032 00007138 ????                <1> 	u.cdir:	  resw 1
  3033 0000713A ????                <1> 		  resw 1 ; 28/03/2020 - reserved for 32 bit inode number
  3034                              <1> 	;u.cdrv:  resw 1 ; 17/04/2020 (dword alignment) 
  3035 0000713C ??                  <1> 	u.cdrv:   resb 1 ; 01/05/2021
  3036 0000713D ??                  <1> 		  resb 1 ; 01/05/2021 (dword alignment)
  3037                              <1> 	;u.fp:	  resb 10 ; Retro UNIX 386 v1
  3038 0000713E <res Ah>            <1> 	u.fp:	  resb OPENFILES ; Retro UNIX 386 v2 ; 28/03/2020 
  3039                              <1> 	u.fsp:	  ; 16/05/2021
  3040 00007148 ????????            <1> 	u.fofp:	  resd 1 ; 16/05/2021 (pointer to fsp entry)
  3041 0000714C ????????            <1> 	u.dirp:	  resd 1
  3042 00007150 ????????            <1> 	u.namep:  resd 1
  3043 00007154 ????????            <1> 	u.off:	  resd 1
  3044 00007158 ????????            <1> 		  resd 1 ; 08/03/2020 - Retro UNIX 386 v2 - 64 bit fptr
  3045 0000715C ????????            <1> 	u.base:	  resd 1
  3046 00007160 ????????            <1> 	u.count:  resd 1
  3047 00007164 ????????            <1> 	u.nread:  resd 1
  3048 00007168 ????????            <1> 	u.break:  resd 1 ; break
  3049                              <1> 	; 16/05/2021 (Retro UNIX 386 v2)
  3050 0000716C ??                  <1> 	u.mode:   resb 1 ; 16/05/2021 (sysread, syswrite, 'rdwr' file mode)
  3051                              <1> 	; 10/01/2017 (TRDOS 386, relocation and dword alignment)
  3052                              <1> 	; tty number (rtty, rcvt, wtty)
  3053 0000716D ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  3054 0000716E ????                <1> 	u.ttyp:	  resw 1 
  3055 00007170 <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  3056                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  3057 00007180 ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  3058 00007181 ??                  <1> 		  resb 1 ; 17/04/2020
  3059 00007182 ??                  <1> 	u.pri:	  resb 1 ; Modification: 21/05/2016 (priority levels: 0, 1, 2)
  3060 00007183 ??                  <1> 		  resb 1 ; 17/04/2020
  3061                              <1> 	; 10/06/2021
  3062                              <1> 	;u.signal: resw 1 ; 21/05/2021 - Retro UNIX 386 v2
  3063                              <1> 	;	  resw 1 ; reserved ; 21/05/2021	
  3064 00007184 ????                <1> 	u.intr:	  resw 1
  3065 00007186 ????                <1> 	u.quit:	  resw 1
  3066                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  3067                              <1> 	;u.ilgins: resw 1 ; 10/01/2017
  3068                              <1> 	;u.cdrv:  resw 1 ; cdev ; 17/04/2020 (moved to up)
  3069                              <1> 	;u.uid:	  resb 1 ; uid
  3070                              <1> 	;u.ruid:  resb 1
  3071 00007188 ??                  <1> 	u.bsys:	  resb 1
  3072 00007189 ??                  <1> 	u.uno:	  resb 1
  3073 0000718A ????                <1>         u.uid:	  resw 1 ; uid	; 27/03/2021 - Retro UNIX 386 v2
  3074 0000718C ????                <1> 	u.ruid:	  resw 1	; 16 bit uid
  3075 0000718E ??                  <1> 	u.gid:	  resb 1 ; gid 	; 27/03/2021 - Retro UNIX 386 v2
  3076 0000718F ??                  <1> 	u.rgid:	  resb 1
  3077                              <1> 	; 20/05/2021 - Retro UNIX 386 v2
  3078 00007190 ????????            <1> 	u.procp:  resd 1 ; /* pointer to proc structure */		
  3079 00007194 ????????            <1> 	u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  3080 00007198 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  3081 0000719C ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  3082 000071A0 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  3083                              <1> 		; 24/10/2021 (32 bit value for Retro UNIX 386 v2)
  3084 000071A4 ????????            <1> 	u.pcount: resd 1 ; 20/05/2015 (byte -transfer- count for page)
  3085                              <1> 	;u.pncount: resw 1 
  3086                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  3087                              <1> 	;u.pnbase:  resd 1 
  3088                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  3089 000071A8 ????                <1> 	u.rsvd:	  resw 1 ; 04/12/2021 (dword alignment)
  3090                              <1> 			 ; 09/06/2015
  3091 000071AA ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign
  3092                              <1> 		; 08/03/2020 (block device read/write flag for 'sioreg')		
  3093 000071AB ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  3094                              <1> 			 ; 24/07/2015 - 24/06/2015
  3095                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  3096                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  3097                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  3098                              <1>  			 ; 24/06/2015	  	
  3099                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  3100                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  3101                              <1> 	; last error number
  3102 000071AC ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  3103                              <1> 			; Retro UNIX 8086/386 v1 feature only!
  3104                              <1> 			; 21/09/2015 (debugging - page fault analyze)
  3105 000071B0 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  3106                              <1> 		; 29/05/2021 - Retro UNIX 386 v2, 2021 (sleep, psig)
  3107 000071B4 ????????            <1> 	u.signal: resd 1 ; unix signal recognition (enabling, accepting) bits	
  3108 000071B8 ??                  <1> 	u.srb:	  resb 1 ; signal handling/responding method
  3109 000071B9 ??                  <1> 	u.snum:	  resb 1 ; signal number (last signal number)
  3110 000071BA ??                  <1> 	u.exit:	  resb 1 ; exit code ; 30/05/2021 - Retro UNIX 386 v2
  3111 000071BB ??                  <1> 	u.s_lock: resb 1 ; signal handling (phase) lock	
  3112 000071BC ????????            <1> 	u.s_addr: resd 1 ; Signal Response Byte or signal handler (callback) address
  3113 000071C0 ????????            <1> 	u.s_time: resd 1 ; signal time in unix epoch format		
  3114                              <1> 		; 19/12/2016 (TRDOS 386)	
  3115 000071C4 ????????            <1> 	u.tcb:	  resd 1 ; Timer callback address/flag which will be used by timer int
  3116                              <1> 		; 13/01/2017 (TRDOS 386)
  3117 000071C8 ??                  <1> 	u.t_lock: resb 1 ; Timer interrupt (callback) lock (unlocked by 'sysrele')
  3118 000071C9 ??                  <1> 	u.t_mode: resb 1 ; running mode during timer interrupt (0= system, 0FFh= user)
  3119                              <1> 		; 26/02/2017 (TRDOS 386)
  3120 000071CA ??                  <1> 	u.irqc:	  resb 1  ; Count of IRQ callback services (IRQs in use)
  3121                              <1> 		; 28/02/2017 (TRDOS 386) 
  3122 000071CB ??                  <1> 	u.irqwait: resb 1 ; IRQ waiting for callback service flag (IRQ number, If > 0)
  3123 000071CC ??                  <1> 	u.r_lock:  resb 1 ; 'IRQ callback service is in progress' flag (IRQ lock)
  3124 000071CD ??                  <1> 	u.r_mode:  resb 1 ; running mode during hardware interrupt
  3125                              <1> 		; 07/02/2020 - Retro UNIX 386 v2
  3126 000071CE ??                  <1> 	u.redir:  resb 1 ; device func redirection permitted by user (if u.redir > 0)
  3127                              <1> 		; 26/02/2020 - Retro UNIX 386 v2
  3128 000071CF ??                  <1> 	u.rwm:	  resb 1  ; read & write mode for devices/drives, 0 = direct, 1 = fs r/w 
  3129                              <1> 		; 24/02/2020 - Retro UNIX 386 v2
  3130                              <1> 		; 24/10/2021 (32 bit value)
  3131 000071D0 ????????            <1> 	u.scount: resd 1 ; sub byte count ; 22/03/2020 
  3132                              <1> 		; 07/03/2020 - Retro UNIX 386 v2
  3133 000071D4 ????                <1> 	u.bps:	  resw 1 ; u.bps = bytes per sector, for readi and writei
  3134 000071D6 ????                <1> 		  resw 1 ; 24/10/2021 (32 bit value for using with 32 bit registers)	
  3135                              <1> 		; 23/03/2020 - Retro UNIX 386 v2
  3136 000071D8 ????                <1> 	u.timeout: resw 1 ; timeout setting (seconds) -for 'sleep'-
  3137                              <1> 		; 28/04/2020 - Retro UNIX 386 v2
  3138 000071DA ??                  <1> 	u.lock:	  resb 1 ; Device lock flag (bit 0 is for device/disk read/write)
  3139                              <1> 		; 24/04/2020
  3140                              <1> 		; 17/04/2020 - Retro UNIX 386 v2
  3141 000071DB ??                  <1> 	u.ifs:	  resb 1 ; (current) installable file system driver index number
  3142                              <1> 		; 25/03/2020
  3143                              <1> 		; 20/03/2020
  3144                              <1> 	;u.lcount: resd 1 ; last byte count for 'writei' (for restoring write count)	
  3145                              <1> 
  3146                              <1> 		; 08/03/2020 - Retro UNIX 386 v2 ('sioreg, 'readi')
  3147                              <1> 	;u.limit: resd 1  ; disk/file size limit for block device read/write ('sioreg')			
  3148                              <1> 	;	  resd 1  ; 08/03/2020 - 64 bit limit (disk size in bytes)
  3149                              <1> 	;	; 26/02/2020 - Retro UNIX 386 v2
  3150                              <1> 	;u.sector: resd 1  ; current sector (for readi and writei, device r/w)  		
  3151                              <1> 	;u.buffer: resd 1  ; current buffer (for readi and writei, device r/w) 
  3152                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3153                              <1> 	;u.devmm: resw 1 ; device major (hb) and minor (lb) numbers
  3154                              <1> 	;u.zero:  resw 1 ; 14/03/2020 - Must be ZERO for current version
  3155                              <1> 		; 22/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3156 000071DC ????????            <1> 	u.device: resd 1 ; (blk, chr) device description table (entry) address 	
  3157                              <1> 		; 14/03/2020 - Retro UNIX 386 v2 (sleep, wakeup)
  3158 000071E0 ????????            <1> 	u.function: resd 1 ; device function (read, write)
  3159                              <1> 		; 22/03/2020 - Retro UNIX 386 v2, 2020 (readi, writei)
  3160 000071E4 ????????            <1> 	u.buffer: resd 1  ; for saving buffer header address for 'poke'
  3161 000071E8 ????                <1> 	u.inode:  resw 1  ; for saving inode number of current (device) inode
  3162 000071EA ????                <1> 		  resw 1  ; 18/10/2021 Retro UNIX 386 v2 - 32 bit inode number			
  3163 000071EC ??                  <1> 	u.idev:	  resb 1  ; for saving logical drv number of current (dev) inode
  3164                              <1> 		; 04/12/2021
  3165 000071ED ????                <1> 	u.rsvd2:  resw 1  ; (for dword alignment)	
  3166                              <1> 		; 27/02/2017 (TRDOS 386) 
  3167                              <1> ;; 31/12/2021 - temporary !
  3168                              <1> ;	u.fpsave: resb 1  ; TRDOS 386, 'save/restore FPU registers' flag
  3169 000071EF ??                  <1> alignb 4
  3170                              <1> 	; !! wrong sizing in TRDOS 386 v2.0.4 (in 'ubss.s', 28/02/2017) !! 
  3171                              <1> 	;u.fpregs: resb 94 ; 94 byte area for saving and restoring FPU registers
  3172                              <1> 	; 30/05/2021 - Retro UNIX 386 v2
  3173                              <1> ;	u.fpregs: resb 108 ; 108 byte area for saving and restoring FPU registers	
  3174                              <1> alignb 4
  3175                              <1> 
  3176                              <1> U_SIZE	equ $ - user
  3177                              <1> 
  3178                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  3179 000071F0 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3180 000071F4 ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  3181 000071F8 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  3182                              <1> ;ncount: resw 1 ; remain byte count in page for 'namei' & 'sysexec'
  3183                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'ncount')
  3184 000071FC ????????            <1> ncount: resd 1	; remain byte count in page for 'namei' & 'sysexec'
  3185                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  3186                              <1> ; 11/12/2021 - Retro UNIX 386 v1.2 (32 bit 'argc')
  3187 00007200 ????????            <1> argc:	resd 1	; argument count for 'sysexec'
  3188 00007204 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  3189                              <1> 
  3190                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  3191                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  3192 00007208 ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  3193 00007209 ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  3194 0000720A ??                  <1> mget_rw: resb 1 ; 22/11/2021 
  3195 0000720B ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  3196                              <1> 
  3197                              <1> ; 22/11/2021 - Retro UNIX 386 v2 compatibility
  3198                              <1> level:	resd 0  ; level, level+1, level+2, level+3  ; for 'mget' procedure
  3199                              <1> 
  3200                              <1> ;alignb 4
  3201                              <1> 
  3202                              <1> ; 22/08/2015
  3203                              <1> ;buffer: resb nbuf * 520
  3204                              <1> 
  3205 0000720C ????????????????    <1> sb0:	resd 2
  3206                              <1> ;s:
  3207                              <1> ; (root disk) super block buffer
  3208                              <1> systm:
  3209                              <1> 	; 27/11/2021 - Retro UNIX 386 v2 compatible super block
  3210                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  3211                              <1> 	; 11/03/2013. 
  3212                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3213                              <1> 	;s.
  3214                              <1> 
  3215                              <1> 	;resw 1
  3216                              <1> 	;resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3217                              <1> 	;resw 1
  3218                              <1> 	;resb 32 ; 256+40 inodes ; original UNIX v1 value: 64
  3219                              <1> 	;s.time: resd 1
  3220                              <1> 	;s.syst: resd 1
  3221                              <1>         ;s.wait_: resd 1 ; wait
  3222                              <1> 	;s.idlet: resd 1
  3223                              <1> 	;s.chrgt: resd 1
  3224                              <1> 	;s.drerr: resw 1
  3225                              <1> 
  3226                              <1> 	; 27/11/2021
  3227 00007214 <res 200h>          <1> 	resb 512	
  3228                              <1> 
  3229                              <1> ;S_SIZE	equ $ - systm
  3230                              <1> 
  3231                              <1> 	;resb 512-S_SIZE ; 03/06/2015	 
  3232                              <1> 
  3233 00007414 ????????????????    <1> sb1:	resd 2
  3234                              <1> ; (mounted disk) super block buffer
  3235                              <1> mount:	
  3236 0000741C <res 200h>          <1> 	resb 512  ; 03/06/2015
  3237                              <1> 
  3238                              <1> ; 27/11/2021
  3239                              <1> ; these are will be used for disk block allocation ('alloc' proc)
  3240                              <1> free_map_offset: 
  3241 0000761C ????????            <1> 		resd 1
  3242 00007620 ????????            <1> free_map_index:	resd 1
  3243                              <1> free_map_sector:
  3244 00007624 ????????            <1> 		resd 1
  3245                              <1> ;free_map_buffer:
  3246                              <1> ;		resd 1
  3247                              <1> 
  3248                              <1> ; 27/11/2021 - temporary !
  3249 00007628 ????????            <1> s.time:		resd 1
  3250                              <1> 
  3251                              <1> ;/ ux -- unix
  3252                              <1> ;
  3253                              <1> ;systm:
  3254                              <1> ;
  3255                              <1> ;	.=.+2
  3256                              <1> ;	.=.+128.
  3257                              <1> ;	.=.+2
  3258                              <1> ;	.=.+64.
  3259                              <1> ;	s.time: .=.+4
  3260                              <1> ;	s.syst: .=.+4
  3261                              <1> ;	s.wait: .=.+4
  3262                              <1> ;	s.idlet:.=.+4
  3263                              <1> ;	s.chrgt:.=.+4
  3264                              <1> ;	s.drerr:.=.+2
  3265                              <1> ;inode:
  3266                              <1> ;	i.flgs: .=.+2
  3267                              <1> ;	i.nlks: .=.+1
  3268                              <1> ;	i.uid:  .=.+1
  3269                              <1> ;	i.size: .=.+2
  3270                              <1> ;	i.dskp: .=.+16.
  3271                              <1> ;	i.ctim: .=.+4
  3272                              <1> ;	i.mtim: .=.+4
  3273                              <1> ;	. = inode+32.
  3274                              <1> ;mount:	.=.+1024.
  3275                              <1> ;proc:
  3276                              <1> ;	p.pid:  .=.+[2*nproc]
  3277                              <1> ;	p.dska: .=.+[2*nproc]
  3278                              <1> ;	p.ppid: .=.+[2*nproc]
  3279                              <1> ;	p.break:.=.+[2*nproc]
  3280                              <1> ;	p.link: .=.+nproc
  3281                              <1> ;	p.stat: .=.+nproc
  3282                              <1> ;tty:
  3283                              <1> ;	. = .+[ntty*8.]
  3284                              <1> ;fsp:	.=.+[nfiles*8.]
  3285                              <1> ;bufp:	.=.+[nbuf*2]+6
  3286                              <1> ;sb0:	.=.+8
  3287                              <1> ;sb1:	.=.+8
  3288                              <1> ;swp:	.=.+8
  3289                              <1> ;ii:	.=.+2
  3290                              <1> ;idev:	.=.+2
  3291                              <1> ;cdev:	.=.+2
  3292                              <1> ;deverr: .=.+12.
  3293                              <1> ;active: .=.+2
  3294                              <1> ;rfap:	.=.+2
  3295                              <1> ;rkap:	.=.+2
  3296                              <1> ;tcap:	.=.+2
  3297                              <1> ;tcstate:.=.+2
  3298                              <1> ;tcerrc: .=.+2
  3299                              <1> ;mnti:	.=.+2
  3300                              <1> ;mntd:	.=.+2
  3301                              <1> ;mpid:	.=.+2
  3302                              <1> ;clockp: .=.+2
  3303                              <1> ;rootdir:.=.+2
  3304                              <1> ;toutt:	.=.+16.
  3305                              <1> ;touts: .=.+32.
  3306                              <1> ;runq:	.=.+6
  3307                              <1> ;
  3308                              <1> ;wlist:	.=.+40.
  3309                              <1> ;cc:	.=.+30.
  3310                              <1> ;cf:	.=.+31.
  3311                              <1> ;cl:	.=.+31.
  3312                              <1> ;clist:	.=.+510.
  3313                              <1> ;imod:	.=.+1
  3314                              <1> ;smod:	.=.+1
  3315                              <1> ;mmod:	.=.+1
  3316                              <1> ;uquant: .=.+1
  3317                              <1> ;sysflg: .=.+1
  3318                              <1> ;pptiflg:.=.+1
  3319                              <1> ;ttyoch: .=.+1
  3320                              <1> ; .even
  3321                              <1> ; .=.+100.; sstack:
  3322                              <1> ;buffer: .=.+[ntty*140.]
  3323                              <1> ;	.=.+[nbuf*520.]
  3324                              <1> ;
  3325                              <1> ; . = core-64.
  3326                              <1> ;user:
  3327                              <1> ;	u.sp:    .=.+2
  3328                              <1> ;	u.usp:   .=.+2
  3329                              <1> ;	u.r0:    .=.+2
  3330                              <1> ;	u.cdir:  .=.+2
  3331                              <1> ;	u.fp:    .=.+10.
  3332                              <1> ;	u.fofp:  .=.+2
  3333                              <1> ;	u.dirp:  .=.+2
  3334                              <1> ;	u.namep: .=.+2
  3335                              <1> ;	u.off:   .=.+2
  3336                              <1> ;	u.base:  .=.+2
  3337                              <1> ;	u.count: .=.+2
  3338                              <1> ;	u.nread: .=.+2
  3339                              <1> ;	u.break: .=.+2
  3340                              <1> ;	u.ttyp:  .=.+2
  3341                              <1> ;	u.dirbuf:.=.+10.
  3342                              <1> ;	u.pri:   .=.+2
  3343                              <1> ;	u.intr:  .=.+2
  3344                              <1> ;	u.quit:  .=.+2
  3345                              <1> ;	u.emt:   .=.+2
  3346                              <1> ;	u.ilgins:.=.+2
  3347                              <1> ;	u.cdev:  .=.+2
  3348                              <1> ;	u.uid:   .=.+1
  3349                              <1> ;	u.ruid:  .=.+1
  3350                              <1> ;	u.bsys:  .=.+1
  3351                              <1> ;	u.uno:   .=.+1
  3352                              <1> ;. = core
  2647                                  
  2648                                  ; 17/04/2021
  2649                                  ; (memory page swap parameters are disabled as temporary)
  2650                                  ;
  2651                                  ;; Memory (swap) Data (11/03/2015)
  2652                                  ; 09/03/2015
  2653                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2654                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2655                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2656                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2657                                  ;swpd_next:  resd 1 ; next free page block
  2658                                  ;swpd_last:  resd 1 ; last swap page block	
  2659                                  
  2660                                  alignb 4
  2661                                  
  2662                                  ; 10/07/2015
  2663                                  ; 28/08/2014
  2664 0000762C ????????                error_code:	resd 1
  2665                                  ; 29/08/2014
  2666 00007630 ????????                FaultOffset:	resd 1
  2667                                  ; 21/09/2015
  2668 00007634 ????????                PF_Count:	resd 1	; total page fault count
  2669                                  		       	; (for debugging - page fault analyze)
  2670                                  		 	; 'page _fault_handler' (memory.s)
  2671                                  			; 'sysgeterr' (u9.s)
  2672                                  ;; 21/08/2015
  2673                                  ;;buffer: resb (nbuf*520) ;; sysdefs.s, ux.s
  2674                                  
  2675                                  ; 27/12/2021
  2676 00007638 <res C30h>              buffer: resb (nbuf*520)
  2677                                  
  2678                                  bss_end:
  2679                                  
  2680                                  ; 12/12/2021
  2681                                  BSS_SIZE equ bss_end - bss_start
  2682                                  
  2683                                  ; 27/12/2013
  2684                                  _end:  ; end of kernel code (and read only data, just before bss)
