     1                                  ; ****************************************************************************
     2                                  ; UNIX386.ASM (RETRO UNIX 386 Kernel) - v0.2.1.2
     3                                  ; ----------------------------------------------------------------------------
     4                                  ; NASM version 2.15 (unix386.s)
     5                                  ;
     6                                  ; RETRO UNIX 386 (Retro Unix == Turkish Rational Unix)
     7                                  ; Operating System Project (v0.2) by ERDOGAN TAN (Beginning: 24/12/2013)
     8                                  ;
     9                                  ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
    10                                  ; (v0.1 - Beginning: 11/07/2012)
    11                                  ;
    12                                  ; [ Last Modification: 29/04/2022 (v0.2.1.2) ]
    13                                  ;	 04/02/2016 - Retro UNIX 386 v1.1 (Retro UNIX Kernel v0.2.1.0)	
    14                                  ;	 31/12/2021 - BugFix and Code Optimization (v0.2.1.1)
    15                                  ;	 03/03/2022 - Code Optimization and BugFix (v0.2.1.2) - 02/01/2022
    16                                  ;	 04/04/2022 - Inode Table/List Address Modification (v0.2.1.2) -u5.s-
    17                                  ;	 22/04/2022 - BugFix ('mget' -u5.s-)
    18                                  ;	 29/04/2022 - BugFix ('syschmod' -u2.s-) 
    19                                  ;
    20                                  ; Derived from UNIX Operating System (v1.0 for PDP-11) 
    21                                  ; (Original) Source Code by Ken Thompson (1971-1972)
    22                                  ; <Bell Laboratories (17/3/1972)>
    23                                  ; <Preliminary Release of UNIX Implementation Document>
    24                                  ;
    25                                  ; Derived from 'UNIX v7/x86' source code by Robert Nordier (1999)
    26                                  ; UNIX V7/x86 source code: see www.nordier.com/v7x86 for details.
    27                                  ;
    28                                  ; ****************************************************************************
    29                                  ; 31/12/2021 - 22/04/2022
    30                                  ; nasm unix386.s -l unix386.txt -o unix386 -Z error.txt
    31                                  ; ('unixcopy' utility is used for updating retro unix kernel on runix fs disk)
    32                                  
    33                                  ; 02/01/2022 - Code Optimization
    34                                  ; Runix Kernel v0.2.1.2
    35                                  ; 24/12/2021 - BugFix and Code Optimization
    36                                  ; Runix Kernel v0.2.1.1 
    37                                  
    38                                  ; 24/12/2013
    39                                  
    40                                  ; Entering protected mode:
    41                                  ; Derived from 'simple_asm.txt' source code file and 
    42                                  ; 'The world of Protected mode' tutorial/article by Gregor Brunmar (2003)
    43                                  ; (gregor.brunmar@home.se)
    44                                  ; http://www.osdever.net/tutorials/view/the-world-of-protected-mode
    45                                  ;
    46                                  
    47                                  ; "The Real, Protected, Long mode assembly tutorial for PCs" 
    48                                  ; by Michael Chourdakis (2009) 
    49                                  ; http://www.codeproject.com/Articles/45788/
    50                                  ; http://www.michaelchourdakis.com
    51                                  ;
    52                                  
    53                                  ; Global Descriptor Table:
    54                                  ; Derived from 'head.s" source code of Linux v1.0 kernel
    55                                  ; by Linus Torvalds (1991-1992)
    56                                  ;
    57                                  
    58                                  KLOAD	equ 10000h ; Kernel loading address
    59                                  	; NOTE: Retro UNIX 8086 v1 /boot code loads kernel at 1000h:0000h
    60                                  KCODE	equ 08h	; Code segment descriptor (ring 0)
    61                                  KDATA	equ 10h	; Data segment descriptor (ring 0)
    62                                  ; 19/03/2015
    63                                  UCODE	equ 1Bh ; 18h + 3h  (ring 3)
    64                                  UDATA	equ 23h ; 20h + 3h  (ring 3)
    65                                  ; 24/03/2015
    66                                  TSS	equ 28h	; Task state segment descriptor (ring 0)
    67                                  ; 19/03/2015
    68                                  CORE	equ 400000h  ; Start of USER's virtual/linear address space 
    69                                  		     ; (at the end of the 1st 4MB)
    70                                  ECORE	equ 0FFC00000h ; End of USER's virtual address space (4GB - 4MB)
    71                                  		     ; ULIMIT = (ECORE/4096) - 1 = 0FFBFFh (in GDT)
    72                                  
    73                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
    74                                  ;; 27/12/2013
    75                                  ;KEND	equ KLOAD + 65536 ; (28/12/2013) (end of kernel space)
    76                                  
    77                                  ; IBM PC/AT BIOS ----- 10/06/85 (postequ.inc)
    78                                  ;--------- CMOS TABLE LOCATION ADDRESS'S -------------------------------------
    79                                  CMOS_SECONDS	EQU	00H		; SECONDS (BCD)
    80                                  CMOS_MINUTES	EQU	02H		; MINUTES (BCD)	
    81                                  CMOS_HOURS	EQU	04H		; HOURS (BCD)
    82                                  CMOS_DAY_WEEK	EQU	06H		; DAY OF THE WEEK  (BCD)
    83                                  CMOS_DAY_MONTH	EQU	07H		; DAY OF THE MONTH (BCD) 
    84                                  CMOS_MONTH	EQU	08H		; MONTH (BCD)
    85                                  CMOS_YEAR	EQU	09H		; YEAR (TWO DIGITS) (BCD)
    86                                  CMOS_CENTURY	EQU	32H		; DATE CENTURY BYTE (BCD)
    87                                  CMOS_REG_A	EQU	0AH		; STATUS REGISTER A
    88                                  CMOS_REG_B	EQU	00BH		; STATUS REGISTER B  ALARM
    89                                  CMOS_REG_C	EQU	00CH		; STATUS REGISTER C  FLAGS
    90                                  CMOS_REG_D	EQU	0DH		; STATUS REGISTER D  BATTERY
    91                                  CMOS_SHUT_DOWN	EQU	0FH		; SHUTDOWN STATUS COMMAND BYTE
    92                                  ;----------------------------------------
    93                                  ;	CMOS EQUATES FOR THIS SYSTEM	;
    94                                  ;-----------------------------------------------------------------------------
    95                                  CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
    96                                  CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
    97                                  NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
    98                                  					; HIGH BIT OF CMOS LOCATION ADDRESS
    99                                  
   100                                  ; Memory Allocation Table Address
   101                                  ; 05/11/2014
   102                                  ; 31/10/2014
   103                                  MEM_ALLOC_TBL	equ	100000h		; Memory Allocation Table at the end of
   104                                  					; the 1st 1 MB memory space.
   105                                  					; (This address must be aligned
   106                                  					;  on 128 KB boundary, if it will be
   107                                  					;  changed later.)
   108                                  					; ((lower 17 bits of 32 bit M.A.T.
   109                                  					;   address must be ZERO)).
   110                                  					; ((((Reason: 32 bit allocation 
   111                                  					;     instructions, dword steps)))
   112                                  					; (((byte >> 12 --> page >> 5)))  
   113                                  ;04/11/2014	
   114                                  PDE_A_PRESENT	equ	1		; Present flag for PDE
   115                                  PDE_A_WRITE	equ 	2		; Writable (write permission) flag
   116                                  PDE_A_USER	equ	4		; User (non-system/kernel) page flag
   117                                  ;
   118                                  PTE_A_PRESENT	equ	1		; Present flag for PTE (bit 0)
   119                                  PTE_A_WRITE	equ 	2		; Writable (write permission) flag (bit 1)
   120                                  PTE_A_USER	equ	4		; User (non-system/kernel) page flag (bit 2)
   121                                  PTE_A_ACCESS    equ	32		; Accessed flag (bit 5) ; 09/03/2015
   122                                  
   123                                  ; 17/02/2015 (unix386.s)
   124                                  ; 10/12/2014 - 30/12/2014 (0B000h -> 9000h) (dsectrm2.s)
   125                                  DPT_SEGM equ 09000h  ; FDPT segment (EDD v1.1, EDD v3)
   126                                  ;
   127                                  HD0_DPT	 equ 0	    ; Disk parameter table address for hd0
   128                                  HD1_DPT	 equ 32	    ; Disk parameter table address for hd1
   129                                  HD2_DPT	 equ 64	    ; Disk parameter table address for hd2
   130                                  HD3_DPT	 equ 96	    ; Disk parameter table address for hd3
   131                                  
   132                                  
   133                                  ; FDPT (Phoenix, Enhanced Disk Drive Specification v1.1, v3.0)
   134                                  ;      (HDPT: Programmer's Guide to the AMIBIOS, 1993)
   135                                  ;
   136                                  FDPT_CYLS	equ 0 ; 1 word, number of cylinders
   137                                  FDPT_HDS	equ 2 ; 1 byte, number of heads
   138                                  FDPT_TT		equ 3 ; 1 byte, A0h = translated FDPT with logical values
   139                                  		      ; otherwise it is standard FDPT with physical values 	
   140                                  FDPT_PCMP	equ 5 ; 1 word, starting write precompensation cylinder
   141                                  		      ; (obsolete for IDE/ATA drives)
   142                                  FDPT_CB		equ 8 ; 1 byte, drive control byte
   143                                  			; Bits 7-6 : Enable or disable retries (00h = enable)
   144                                  			; Bit 5	: 1 = Defect map is located at last cyl. + 1
   145                                  			; Bit 4 : Reserved. Always 0
   146                                  			; Bit 3 : Set to 1 if more than 8 heads
   147                                  			; Bit 2-0 : Reserved. Alsways 0
   148                                  FDPT_LZ		equ 12 ; 1 word, landing zone (obsolete for IDE/ATA drives)
   149                                  FDPT_SPT	equ 14 ; 1 byte, sectors per track
   150                                  
   151                                  ; Floppy Drive Parameters Table (Programmer's Guide to the AMIBIOS, 1993)
   152                                  ; (11 bytes long) will be used by diskette handler/bios
   153                                  ; which is derived from IBM PC-AT BIOS (DISKETTE.ASM, 21/04/1986).						 	  		 	  
   154                                  
   155                                  [BITS 16]       ; We need 16-bit intructions for Real mode
   156                                  
   157                                  [ORG 0]
   158                                  
   159                                  KSTART: ; 01/01/2022
   160                                   
   161                                  	; 12/11/2014
   162                                  	; Save boot drive number (that is default root drive)
   163 00000000 8816[CA65]              	mov	[boot_drv], dl ; physical drv number
   164                                  
   165                                  	; Determine installed memory
   166                                  	; 31/10/2014
   167                                  	;
   168 00000004 B801E8                  	mov	ax, 0E801h ; Get memory size 
   169 00000007 CD15                    	int	15h	   ; for large configurations
   170 00000009 7308                    	jnc	short chk_ms
   171 0000000B B488                    	mov	ah, 88h    ; Get extended memory size 
   172 0000000D CD15                    	int	15h
   173                                  	;	   
   174                                  	;mov	al, 17h	; Extended memory (1K blocks) low byte
   175                                  	;out	70h, al ; select CMOS register
   176                                  	;in	al, 71h ; read data (1 byte)
   177                                  	;mov	cl, al
   178                                  	;mov	al, 18h ; Extended memory (1K blocks) high byte
   179                                  	;out	70h, al ; select CMOS register
   180                                  	;in	al, 71h ; read data (1 byte)
   181                                  	;mov	ch, al
   182                                   	;      
   183 0000000F 89C1                    	mov	cx, ax
   184 00000011 31D2                    	xor	dx, dx
   185                                  chk_ms:
   186 00000013 890E[6468]              	mov	[mem_1m_1k], cx
   187 00000017 8916[6868]              	mov	[mem_16m_64k], dx
   188                                  	; 05/11/2014
   189                                  	;and	dx, dx
   190                                  	;jz	short L2
   191 0000001B 81F90004                        cmp     cx, 1024
   192 0000001F 7351                    	jnb	short L0
   193                                  		 ; insufficient memory_error	
   194                                  		 ; Minimum 2 MB memory is needed... 
   195                                  	; 05/11/2014
   196                                  	; (real mode error printing)
   197 00000021 FB                      	sti
   198 00000022 BE[3600]                	mov	si, msg_out_of_memory
   199 00000025 BB0700                  	mov	bx, 7
   200 00000028 B40E                    	mov	ah, 0Eh	; write tty
   201                                  oom_1:
   202 0000002A AC                      	lodsb
   203 0000002B 08C0                    	or	al, al
   204 0000002D 7404                    	jz	short oom_2
   205 0000002F CD10                    	int	10h
   206 00000031 EBF7                    	jmp	short oom_1
   207                                  oom_2:
   208 00000033 F4                              hlt
   209 00000034 EBFD                    	jmp	short oom_2
   210                                  
   211                                  ; 02/01/2022
   212                                  ; 05/11/2014
   213                                  msg_out_of_memory:
   214 00000036 070D0A                  	db 	07h, 0Dh, 0Ah
   215 00000039 496E73756666696369-             db      'Insufficient memory !'
   215 00000042 656E74206D656D6F72-
   215 0000004B 792021             
   216 0000004E 0D0A                    	db	0Dh, 0Ah
   217                                  _int13h_48h_buffer: ; 02/01/2022 (Runix Kernel v0.2.1.2, 'diskinit.inc')
   218 00000050 284D696E696D756D20-     	db	'(Minimum 2MB memory is needed.)'
   218 00000059 324D42206D656D6F72-
   218 00000062 79206973206E656564-
   218 0000006B 65642E29           
   219 0000006F 0D0A00                   	db	0Dh, 0Ah, 0
   220                                  
   221                                  L0:
   222                                  %include 'diskinit.inc' ; 07/03/2015
   223                              <1> ; Retro UNIX 386 v1 Kernel - DISKINIT.INC
   224                              <1> ; Last Modification: 02/01/2022
   225                              <1> 
   226                              <1> ; DISK I/O SYSTEM INITIALIZATION - Erdogan Tan (Retro UNIX 386 v1 project)
   227                              <1> 
   228                              <1> ; ///////// DISK I/O SYSTEM STRUCTURE INITIALIZATION ///////////////
   229                              <1> 
   230                              <1> 	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   231                              <1> 	; 10/12/2014 - 02/02/2015 - dsectrm2.s
   232                              <1> ;L0:
   233                              <1> 	; 12/11/2014 (Retro UNIX 386 v1 - beginning)
   234                              <1> 	; Detecting disk drives... (by help of ROM-BIOS)
   235 00000072 BA7F00              <1> 	mov	dx, 7Fh
   236                              <1> L1:	
   237 00000075 FEC2                <1> 	inc	dl
   238 00000077 B441                <1> 	mov	ah, 41h ; Check extensions present
   239                              <1> 			; Phoenix EDD v1.1 - EDD v3
   240 00000079 BBAA55              <1> 	mov	bx, 55AAh
   241 0000007C CD13                <1> 	int 	13h
   242 0000007E 721A                <1> 	jc	short L2
   243                              <1> 
   244 00000080 81FB55AA            <1> 	cmp	bx, 0AA55h
   245 00000084 7514                <1> 	jne	short L2
   246 00000086 FE06[CD65]          <1> 	inc	byte [hdc]	; count of hard disks (EDD present)
   247 0000008A 8816[CC65]          <1>         mov     [last_drv], dl  ; last hard disk number
   248 0000008E BB[5065]            <1> 	mov	bx, hd0_type - 80h
   249 00000091 01D3                <1> 	add	bx, dx	 
   250 00000093 880F                <1> 	mov	[bx], cl ; Interface support bit map in CX
   251                              <1> 			 ; Bit 0 - 1, Fixed disk access subset ready
   252                              <1> 			 ; Bit 1 - 1, Drv locking and ejecting ready
   253                              <1> 			 ; Bit 2 - 1, Enhanced Disk Drive Support
   254                              <1>                          ;            (EDD) ready (DPTE ready)
   255                              <1> 			 ; Bit 3 - 1, 64bit extensions are present
   256                              <1>                          ;            (EDD-3)
   257                              <1> 			 ; Bit 4 to 15 - 0, Reserved
   258 00000095 80FA83              <1> 	cmp	dl, 83h	 ; drive number < 83h
   259 00000098 72DB                <1> 	jb	short L1
   260                              <1> L2:
   261                              <1> 	; 23/11/2014
   262                              <1> 	; 19/11/2014
   263 0000009A 30D2                <1> 	xor	dl, dl  ; 0
   264                              <1> 	; 04/02/2016 (esi -> si)
   265 0000009C BE[CE65]            <1> 	mov	si, fd0_type
   266                              <1> L3:
   267                              <1> 	; 14/01/2015
   268 0000009F 8816[CB65]          <1> 	mov	[drv], dl
   269                              <1> 	;
   270 000000A3 B408                <1> 	mov 	ah, 08h ; Return drive parameters
   271 000000A5 CD13                <1> 	int	13h	
   272 000000A7 7210                <1> 	jc	short L4
   273                              <1> 		; BL = drive type (for floppy drives)
   274                              <1> 		; DL = number of floppy drives
   275                              <1> 		;		
   276                              <1> 		; ES:DI = Address of DPT from BIOS
   277                              <1> 		;
   278 000000A9 881C                <1> 	mov	[si], bl ;  Drive type
   279                              <1> 			; 4 = 1.44 MB, 80 track, 3 1/2"
   280                              <1> 	; 14/01/2015
   281 000000AB E8BB01              <1> 	call	set_disk_parms
   282                              <1> 	; 10/12/2014
   283 000000AE 81FE[CE65]          <1> 	cmp	si, fd0_type
   284 000000B2 7705                <1> 	ja	short L4
   285 000000B4 46                  <1> 	inc	si ; fd1_type
   286 000000B5 B201                <1> 	mov	dl, 1
   287 000000B7 EBE6                <1> 	jmp	short L3
   288                              <1> L4:
   289                              <1> 	; Older BIOS (INT 13h, AH = 48h is not available)
   290 000000B9 B27F                <1> 	mov	dl, 7Fh
   291                              <1> 	; 24/12/2014 (Temporary)
   292 000000BB 803E[CD65]00        <1> 	cmp	byte [hdc], 0 ; EDD present or not ?	
   293                              <1> 	;ja	L10       ; yes, all fixed disk operations
   294                              <1> 			  ; will be performed according to
   295                              <1> 			  ; present EDD specification
   296                              <1> 	; 02/01/2022
   297 000000C0 7603                <1> 	jna	short L5
   298 000000C2 E99100              <1> 	jmp	L10
   299                              <1> L5:
   300 000000C5 FEC2                <1> 	inc 	dl
   301 000000C7 8816[CB65]          <1>         mov     [drv], dl
   302 000000CB 8816[CC65]          <1>         mov     [last_drv], dl ; 14/01/2015
   303 000000CF B408                <1> 	mov 	ah, 08h ; Return drive parameters
   304 000000D1 CD13                <1> 	int	13h	; (conventional function)
   305                              <1> 	;jc	L13	; fixed disk drive not ready
   306                              <1> 	; 02/01/2022
   307 000000D3 7303                <1> 	jnc	short L6
   308 000000D5 E98301              <1> 	jmp	L13
   309                              <1> L6:
   310 000000D8 8816[CD65]          <1>         mov     [hdc], dl ; number of drives
   311                              <1> 	;; 14/01/2013
   312                              <1> 	;;push	cx
   313 000000DC E88A01              <1> 	call	set_disk_parms
   314                              <1> 	;;pop	cx
   315                              <1> 	;
   316                              <1> 	;;and	cl, 3Fh	 ; sectors per track (bits 0-6)
   317 000000DF 8A16[CB65]          <1>         mov     dl, [drv]
   318 000000E3 BB0401              <1> 	mov	bx, 65*4 ; hd0 parameters table (INT 41h)	
   319 000000E6 80FA80              <1> 	cmp	dl, 80h
   320 000000E9 7603                <1> 	jna	short L7
   321 000000EB 83C314              <1> 	add	bx, 5*4	 ; hd1 parameters table (INT 46h)
   322                              <1> L7:	
   323 000000EE 31C0                <1> 	xor	ax, ax
   324 000000F0 8ED8                <1> 	mov	ds, ax
   325 000000F2 8B37                <1>         mov     si, [bx]
   326 000000F4 8B4702              <1>         mov     ax, [bx+2] 
   327 000000F7 8ED8                <1> 	mov	ds, ax
   328 000000F9 3A4C0E              <1>         cmp     cl, [si+FDPT_SPT] ; sectors per track 
   329                              <1> 	;jne	L12 ; invalid FDPT
   330                              <1> 	; 02/01/2022
   331 000000FC 7403                <1> 	je	short L7_8
   332 000000FE E95601              <1> 	jmp	L12
   333                              <1> L7_8:
   334 00000101 BF0000              <1> 	mov	di, HD0_DPT
   335 00000104 80FA80              <1> 	cmp	dl, 80h
   336 00000107 7603                <1> 	jna	short L8
   337 00000109 BF2000              <1> 	mov	di, HD1_DPT 
   338                              <1> L8:
   339                              <1> 	; 30/12/2014
   340 0000010C B80090              <1> 	mov	ax, DPT_SEGM
   341 0000010F 8EC0                <1> 	mov	es, ax
   342                              <1> 	; 24/12/2014
   343 00000111 B90800              <1> 	mov	cx, 8
   344 00000114 F3A5                <1> 	rep	movsw  ; copy 16 bytes to the kernel's DPT location
   345 00000116 8CC8                <1> 	mov	ax, cs
   346 00000118 8ED8                <1> 	mov	ds, ax
   347                              <1> 	; 02/02/2015
   348 0000011A 8A0E[CB65]          <1>         mov     cl, [drv]
   349 0000011E 88CB                <1> 	mov	bl, cl
   350 00000120 B8F001              <1> 	mov	ax, 1F0h
   351 00000123 80E301              <1> 	and	bl, 1
   352 00000126 7406                <1> 	jz	short L9
   353 00000128 C0E304              <1> 	shl	bl, 4
   354 0000012B 2D8000              <1> 	sub	ax, 1F0h-170h
   355                              <1> L9:
   356 0000012E AB                  <1> 	stosw	; I/O PORT Base Address (1F0h, 170h)
   357 0000012F 050602              <1> 	add	ax, 206h
   358 00000132 AB                  <1> 	stosw	; CONTROL PORT Address (3F6h, 376h)	
   359 00000133 88D8                <1> 	mov	al, bl
   360 00000135 04A0                <1> 	add	al, 0A0h
   361 00000137 AA                  <1> 	stosb	; Device/Head Register upper nibble
   362                              <1> 	;
   363 00000138 FE06[CB65]          <1> 	inc	byte [drv]
   364 0000013C BB[5065]            <1> 	mov	bx, hd0_type - 80h
   365 0000013F 01CB                <1> 	add	bx, cx
   366 00000141 800F80              <1>         or      byte [bx], 80h  ; present sign (when lower nibble is 0)
   367 00000144 A0[CD65]            <1> 	mov	al, [hdc]
   368 00000147 FEC8                <1> 	dec	al
   369                              <1> 	;jz	L13
   370                              <1> 	; 02/01/2022
   371 00000149 7408                <1> 	jz	short L9_10
   372 0000014B 80FA80              <1> 	cmp	dl, 80h
   373                              <1>         ;jna	L5
   374                              <1> 	;jmp	L13
   375                              <1> 	; 02/01/2022
   376 0000014E 7703                <1> 	ja	short L9_10
   377 00000150 E972FF              <1> 	jmp	L5
   378                              <1> L9_10:
   379 00000153 E90501              <1>         jmp     L13
   380                              <1> L10:
   381 00000156 FEC2                <1> 	inc 	dl
   382                              <1> 	; 25/12/2014
   383 00000158 8816[CB65]          <1> 	mov	[drv], dl
   384 0000015C B408                <1> 	mov 	ah, 08h ; Return drive parameters
   385 0000015E CD13                <1> 	int	13h	; (conventional function)
   386                              <1> 	;jc	L13
   387                              <1> 	; 02/01/2022
   388 00000160 72F1                <1> 	jc	short L9_10
   389                              <1> 	; 14/01/2015
   390 00000162 8A16[CB65]          <1> 	mov	dl, [drv]
   391 00000166 52                  <1> 	push	dx
   392 00000167 51                  <1> 	push	cx
   393 00000168 E8FE00              <1> 	call	set_disk_parms
   394 0000016B 59                  <1> 	pop	cx
   395 0000016C 5A                  <1> 	pop	dx
   396                              <1> 	; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   397                              <1> 	; 04/02/2016 (esi -> si)
   398                              <1> 	;mov	si, _end ; 30 byte temporary buffer address
   399                              <1> 	;		 ; at the '_end' of kernel.
   400                              <1> 	;mov	word [si], 30
   401                              <1> 	; 06/07/2016
   402 0000016D BE[5000]            <1> 	mov	si, _int13h_48h_buffer
   403                              <1> 	; 09/07/2016
   404 00000170 B81E00              <1> 	mov	ax, 001Eh
   405 00000173 8824                <1> 	mov	[si], ah ; 0
   406 00000175 46                  <1> 	inc	si
   407 00000176 8904                <1> 	mov	word [si], ax
   408                              <1>  	; word [si] = 30
   409                              <1> 	;
   410 00000178 B448                <1> 	mov	ah, 48h	 ; Get drive parameters (EDD function)
   411 0000017A CD13                <1> 	int	13h
   412                              <1>         ;jc	L13
   413                              <1> 	; 02/01/2022
   414 0000017C 72D5                <1> 	jc	short L9_10
   415                              <1> 	; 04/02/2016 (ebx -> bx)
   416                              <1> 	; 14/01/2015
   417                              <1> 	;sub	bx, bx
   418 0000017E 28FF                <1> 	sub	bh, bh ; 02/01/2022
   419 00000180 88D3                <1> 	mov	bl, dl
   420 00000182 80EB80              <1> 	sub	bl, 80h
   421 00000185 81C3[D065]          <1> 	add	bx, hd0_type
   422 00000189 8A07                <1> 	mov 	al, [bx]
   423 0000018B 0C80                <1> 	or	al, 80h
   424 0000018D 8807                <1> 	mov 	[bx], al	
   425 0000018F 81EB[CE65]          <1> 	sub	bx, hd0_type - 2 ; 15/01/2015
   426 00000193 81C3[1A66]          <1> 	add	bx, drv.status
   427 00000197 8807                <1> 	mov	[bx], al
   428                              <1> 	; 04/02/2016 (eax -> ax)
   429 00000199 8B4410              <1> 	mov	ax, [si+16]
   430 0000019C 854412              <1> 	test	ax, [si+18]
   431 0000019F 7413                <1> 	jz	short L10_A0h 
   432                              <1> 			; 'CHS only' disks on EDD system 
   433                              <1> 			;  are reported with ZERO disk size
   434 000001A1 81EB[1A66]          <1> 	sub	bx, drv.status
   435 000001A5 C1E302              <1> 	shl	bx, 2
   436 000001A8 81C3[FE65]          <1> 	add	bx, drv.size ; disk size (in sectors)
   437 000001AC 8907                <1> 	mov	[bx], ax
   438 000001AE 8B4412              <1> 	mov	ax, [si+18]
   439                              <1> 	;mov	[bx], ax
   440                              <1> 	; 02/01/2022 (BugFix)
   441 000001B1 894702              <1> 	mov	[bx+2], ax
   442                              <1> 
   443                              <1> L10_A0h: ; Jump here to fix a ZERO (LBA) disk size problem 
   444                              <1> 	 ; for CHS disks (28/02/2015)
   445                              <1> 	; 30/12/2014
   446 000001B4 BF0000              <1> 	mov	di, HD0_DPT
   447 000001B7 88D0                <1> 	mov	al, dl
   448 000001B9 83E003              <1> 	and 	ax, 3
   449 000001BC C0E005              <1> 	shl	al, 5 ; *32
   450 000001BF 01C7                <1> 	add 	di, ax
   451 000001C1 B80090              <1> 	mov	ax, DPT_SEGM
   452 000001C4 8EC0                <1> 	mov	es, ax
   453                              <1> 	;
   454 000001C6 88E8                <1> 	mov	al, ch	; max. cylinder number (bits 0-7)
   455 000001C8 88CC                <1> 	mov	ah, cl	
   456 000001CA C0EC06              <1> 	shr	ah, 6	; max. cylinder number (bits 8-9)
   457 000001CD 40                  <1>  	inc	ax	; logical cylinders (limit 1024)
   458 000001CE AB                  <1> 	stosw		
   459 000001CF 88F0                <1> 	mov	al, dh	; max. head number
   460 000001D1 FEC0                <1> 	inc	al
   461 000001D3 AA                  <1> 	stosb		; logical heads (limits 256)
   462 000001D4 B0A0                <1> 	mov	al, 0A0h ; Indicates translated table
   463 000001D6 AA                  <1> 	stosb
   464 000001D7 8A440C              <1> 	mov	al, [si+12]
   465 000001DA AA                  <1> 	stosb		 ; physical sectors per track
   466 000001DB 31C0                <1>  	xor	ax, ax
   467                              <1> 	;dec	ax	 ; 02/01/2015 
   468 000001DD AB                  <1> 	stosw		 ; precompensation (obsolete)
   469                              <1> 	;xor	al, al	 ; 02/01/2015	
   470 000001DE AA                  <1> 	stosb		 ; reserved
   471 000001DF B008                <1> 	mov	al, 8	 ; drive control byte
   472                              <1> 		         ; (do not disable retries, 
   473                              <1> 			 ; more than 8 heads)
   474 000001E1 AA                  <1> 	stosb
   475 000001E2 8B4404              <1> 	mov	ax, [si+4]
   476 000001E5 AB                  <1> 	stosw		 ; physical number of cylinders	
   477                              <1> 	;push	ax	 ; 02/01/2015
   478 000001E6 8A4408              <1> 	mov	al, [si+8]
   479 000001E9 AA                  <1> 	stosb		 ; physical num. of heads (limit 16)
   480 000001EA 29C0                <1> 	sub 	ax, ax
   481                              <1> 	;pop	ax	 ; 02/01/2015	
   482 000001EC AB                  <1> 	stosw		 ; landing zone (obsolete)
   483 000001ED 88C8                <1> 	mov	al, cl	 ; logical sectors per track (limit 63)
   484 000001EF 243F                <1> 	and 	al, 3Fh	
   485 000001F1 AA                  <1> 	stosb
   486                              <1> 	;sub	al, al	 ; checksum
   487                              <1> 	;stosb
   488                              <1> 	;
   489 000001F2 83C61A              <1> 	add	si, 26   ; (BIOS) DPTE address pointer
   490 000001F5 AD                  <1> 	lodsw
   491 000001F6 50                  <1> 	push	ax	 ; (BIOS) DPTE offset
   492 000001F7 AD                  <1> 	lodsw
   493 000001F8 50                  <1> 	push	ax	 ; (BIOS) DPTE segment
   494                              <1> 	;
   495                              <1> 	; checksum calculation
   496 000001F9 89FE                <1> 	mov	si, di
   497 000001FB 06                  <1> 	push	es
   498 000001FC 1F                  <1> 	pop	ds
   499                              <1> 	;mov	cx, 16
   500 000001FD B90F00              <1> 	mov 	cx, 15
   501 00000200 29CE                <1> 	sub	si, cx
   502 00000202 30E4                <1> 	xor	ah, ah
   503                              <1> 	;del	cl
   504                              <1> L11:		
   505 00000204 AC                  <1> 	lodsb
   506 00000205 00C4                <1> 	add	ah, al
   507 00000207 E2FB                <1> 	loop	L11
   508                              <1> 	;
   509 00000209 88E0                <1> 	mov	al, ah
   510 0000020B F6D8                <1> 	neg	al	; -x+x = 0
   511 0000020D AA                  <1> 	stosb		; put checksum in byte 15 of the tbl
   512                              <1> 	;
   513 0000020E 1F                  <1> 	pop	ds	; (BIOS) DPTE segment
   514 0000020F 5E                  <1> 	pop	si	; (BIOS) DPTE offset	
   515                              <1> 	;
   516                              <1> 	; 23/02/2015
   517 00000210 57                  <1> 	push	di
   518                              <1> 	; ES:DI points to DPTE (FDPTE) location
   519                              <1> 	;mov	cx, 8
   520 00000211 B108                <1> 	mov	cl, 8
   521 00000213 F3A5                <1> 	rep	movsw	
   522                              <1> 	;
   523                              <1> 	; 23/02/2015
   524                              <1> 	; (P)ATA drive and LBA validation
   525                              <1> 	; (invalidating SATA drives and setting
   526                              <1> 	; CHS type I/O for old type fixed disks)
   527 00000215 5B                  <1> 	pop	bx
   528 00000216 8CC8                <1> 	mov	ax, cs
   529 00000218 8ED8                <1> 	mov	ds, ax
   530 0000021A 268B07              <1> 	mov	ax, [es:bx]
   531 0000021D 3DF001              <1> 	cmp	ax, 1F0h
   532 00000220 7418                <1> 	je	short L11a
   533 00000222 3D7001              <1> 	cmp	ax, 170h
   534 00000225 7413                <1> 	je	short L11a
   535                              <1> 	; invalidation 
   536                              <1> 	; (because base port address is not 1F0h or 170h)
   537 00000227 30FF                <1> 	xor	bh, bh
   538 00000229 88D3                <1> 	mov	bl, dl
   539 0000022B 80EB80              <1> 	sub	bl, 80h
   540 0000022E C687[D065]00        <1> 	mov	byte [bx+hd0_type], 0 ; not a valid disk drive !		
   541 00000233 808F[1C66]F0        <1>         or      byte [bx+drv.status+2], 0F0h ; (failure sign)
   542 00000238 EB14                <1> 	jmp	short L11b
   543                              <1> L11a:	
   544                              <1> 	; LBA validation
   545 0000023A 268A4704            <1> 	mov	al, [es:bx+4] ; Head register upper nibble
   546 0000023E A840                <1> 	test	al, 40h ; LBA bit (bit 6)
   547 00000240 750C                <1> 	jnz	short L11b ; LBA type I/O is OK! (E0h or F0h)
   548                              <1> 	; force CHS type I/O for this drive (A0h or B0h)
   549 00000242 28FF                <1> 	sub	bh, bh
   550 00000244 88D3                <1> 	mov	bl, dl
   551 00000246 80EB80              <1> 	sub	bl, 80h ; 26/02/2015
   552 00000249 80A7[1C66]FE        <1>         and     byte [bx+drv.status+2], 0FEh ; clear bit 0
   553                              <1> 				; bit 0 = LBA ready bit
   554                              <1> 	; 'diskio' procedure will check this bit !
   555                              <1> L11b:
   556 0000024E 3A16[CC65]          <1> 	cmp	dl, [last_drv] ; 25/12/2014
   557 00000252 7307                <1>         jnb     short L13
   558 00000254 E9FFFE              <1>         jmp     L10
   559                              <1> L12:
   560                              <1> 	; Restore data registers
   561 00000257 8CC8                <1> 	mov	ax, cs
   562 00000259 8ED8                <1> 	mov	ds, ax	
   563                              <1> L13:
   564                              <1> 	; 13/12/2014
   565 0000025B 0E                  <1> 	push	cs
   566 0000025C 07                  <1> 	pop	es
   567                              <1> L14:
   568 0000025D B411                <1> 	mov 	ah, 11h
   569 0000025F CD16                <1> 	int 	16h
   570                              <1> 	;jz 	short L15 ; no keys in keyboard buffer
   571                              <1> 	; 02/01/2022
   572 00000261 7466                <1> 	jz	short L16
   573 00000263 B010                <1> 	mov	al, 10h
   574 00000265 CD16                <1> 	int 	16h
   575 00000267 EBF4                <1> 	jmp 	short L14
   576                              <1> L15:
   577                              <1> 
   578                              <1> ; //////
   579                              <1> 
   580                              <1> ; 02/01/2022 - Retro UNIX 386 v1.1 (Runix Kernel v0.2.1.2)
   581                              <1> %if 0
   582                              <1> 	; 24/11/2014
   583                              <1> 	; 19/11/2014
   584                              <1> 	; 14/11/2014
   585                              <1> 	; Temporary code for disk searching code check
   586                              <1> 	;
   587                              <1> 	; This code will show existing (usable) drives and also
   588                              <1> 	; will show EDD interface support status for hard disks		
   589                              <1> 	; (If status bit 7 is 1, Identify Device info is ready,
   590                              <1> 	; no need to get it again in protected mode...) 
   591                              <1> 	;	
   592                              <1> 	; 13/11/2014
   593                              <1> 	mov	bx, 7
   594                              <1> 	mov	ah, 0Eh
   595                              <1> 	mov	al, [fd0_type]
   596                              <1> 	and	al, al
   597                              <1> 	jz	short L15a
   598                              <1> 	mov	dl, al
   599                              <1> 	mov	al, 'F'
   600                              <1> 	int 	10h
   601                              <1> 	mov	al, 'D'
   602                              <1> 	int 	10h
   603                              <1> 	mov	al, '0'
   604                              <1> 	int 	10h
   605                              <1> 	mov	al, ' '
   606                              <1> 	int	10h
   607                              <1> 	call	L15c
   608                              <1> 	mov	al, ' '
   609                              <1> 	int	10h
   610                              <1> 	;
   611                              <1> 	mov	al, [fd1_type]
   612                              <1> 	and	al, al
   613                              <1> 	jz	short L15a
   614                              <1> 	mov	dl, al
   615                              <1> 	mov	al, 'F'
   616                              <1> 	int 	10h
   617                              <1> 	mov	al, 'D'
   618                              <1> 	int 	10h
   619                              <1> 	mov	al, '1'
   620                              <1> 	int 	10h
   621                              <1> 	mov	al, ' '
   622                              <1> 	int	10h
   623                              <1> 	call	L15c
   624                              <1> 	mov	al, ' '
   625                              <1> 	int	10h
   626                              <1> 	mov	al, ' '
   627                              <1> 	int	10h
   628                              <1> L15a:
   629                              <1> 	mov	al, [hd0_type]
   630                              <1> 	and	al, al
   631                              <1> 	jz	short L15b
   632                              <1> 	mov	dl, al
   633                              <1> 	mov	al, 'H'
   634                              <1> 	int 	10h
   635                              <1> 	mov	al, 'D'
   636                              <1> 	int 	10h
   637                              <1> 	mov	al, '0'
   638                              <1> 	int 	10h
   639                              <1> 	mov	al, ' '
   640                              <1> 	int 	10h
   641                              <1> 	call	L15c
   642                              <1> 	mov	al, ' '
   643                              <1> 	int	10h
   644                              <1> 	;
   645                              <1> 	mov	al, [hd1_type]
   646                              <1> 	and	al, al
   647                              <1> 	jz	short L15b
   648                              <1> 	mov	dl, al
   649                              <1> 	mov	al, 'H'
   650                              <1> 	int 	10h
   651                              <1> 	mov	al, 'D'
   652                              <1> 	int 	10h
   653                              <1> 	mov	al, '1'
   654                              <1> 	int 	10h
   655                              <1> 	mov	al, ' '
   656                              <1> 	int 	10h
   657                              <1> 	call	L15c
   658                              <1> 	mov	al, ' '
   659                              <1> 	int	10h
   660                              <1> 	;
   661                              <1> 	mov	al, [hd2_type]
   662                              <1> 	and	al, al
   663                              <1> 	jz	short L15b
   664                              <1> 	mov	dl, al
   665                              <1> 	mov	al, 'H'
   666                              <1> 	int 	10h
   667                              <1> 	mov	al, 'D'
   668                              <1> 	int 	10h
   669                              <1> 	mov	al, '2'
   670                              <1> 	int 	10h
   671                              <1> 	mov	al, ' '
   672                              <1> 	int 	10h
   673                              <1> 	call	L15c
   674                              <1> 	mov	al, ' '
   675                              <1> 	int	10h
   676                              <1> 	;
   677                              <1> 	mov	al, [hd3_type]
   678                              <1> 	and	al, al
   679                              <1> 	jz	short L15b
   680                              <1> 	mov	dl, al
   681                              <1> 	mov	al, 'H'
   682                              <1> 	int 	10h
   683                              <1> 	mov	al, 'D'
   684                              <1> 	int 	10h
   685                              <1> 	mov	al, '3'
   686                              <1> 	int 	10h
   687                              <1> 	mov	al, ' '
   688                              <1> 	int 	10h
   689                              <1> 	call	L15c
   690                              <1> 	mov	al, ' '
   691                              <1> 	int	10h
   692                              <1> 	;
   693                              <1> L15b:
   694                              <1> 	mov	al, 0Dh
   695                              <1> 	int 	10h	
   696                              <1> 	mov	al, 0Ah
   697                              <1> 	int 	10h
   698                              <1> 	;;xor	ah, ah
   699                              <1> 	;;int 	16h	
   700                              <1> 	;
   701                              <1>         ;jmp	L16  ; jmp short L16
   702                              <1>         ; 02/01/2022
   703                              <1> 	jmp	short L16
   704                              <1> 	;
   705                              <1> L15c:
   706                              <1> 	mov	dh, dl
   707                              <1> 	shr	dh, 4
   708                              <1> 	add	dh, 30h
   709                              <1> 	and	dl, 15
   710                              <1> 	add	dl, 30h
   711                              <1> 	mov	al, dh
   712                              <1> 	int	10h
   713                              <1> 	mov	al, dl
   714                              <1> 	int	10h
   715                              <1> 	retn
   716                              <1> 	;
   717                              <1> 	; end of temporary code for disk searching code check
   718                              <1> 
   719                              <1> %endif
   720                              <1> 
   721                              <1> ; //////
   722                              <1> 
   723                              <1> set_disk_parms:
   724                              <1> 	; 04/02/2016 (ebx -> bx)
   725                              <1> 	; 10/07/2015
   726                              <1> 	; 14/01/2015
   727                              <1> 	;push	bx
   728 00000269 28FF                <1> 	sub	bh, bh
   729 0000026B 8A1E[CB65]          <1> 	mov	bl, [drv]
   730 0000026F 80FB80              <1> 	cmp	bl, 80h
   731 00000272 7203                <1> 	jb	short sdp0
   732 00000274 80EB7E              <1> 	sub	bl, 7Eh
   733                              <1> sdp0:	
   734 00000277 81C3[1A66]          <1> 	add	bx, drv.status
   735 0000027B C60780              <1>   	mov	byte [bx], 80h ; 'Present' flag
   736                              <1> 	;
   737 0000027E 88E8                <1> 	mov	al, ch ; last cylinder (bits 0-7)
   738 00000280 88CC                <1> 	mov	ah, cl ; 
   739 00000282 C0EC06              <1> 	shr	ah, 6  ; last cylinder (bits 8-9)
   740 00000285 81EB[1A66]          <1> 	sub	bx, drv.status
   741 00000289 D0E3                <1> 	shl	bl, 1
   742 0000028B 81C3[D465]          <1> 	add	bx, drv.cylinders
   743 0000028F 40                  <1> 	inc	ax  ; convert max. cyl number to cyl count		
   744 00000290 8907                <1> 	mov	[bx], ax
   745 00000292 50                  <1> 	push	ax ; ** cylinders
   746 00000293 81EB[D465]          <1> 	sub	bx, drv.cylinders
   747 00000297 81C3[E265]          <1> 	add	bx, drv.heads
   748 0000029B 30E4                <1> 	xor	ah, ah
   749 0000029D 88F0                <1> 	mov	al, dh ; heads
   750 0000029F 40                  <1> 	inc	ax
   751 000002A0 8907                <1> 	mov	[bx], ax
   752 000002A2 81EB[E265]          <1>         sub     bx, drv.heads
   753 000002A6 81C3[F065]          <1>         add     bx, drv.spt
   754 000002AA 30ED                <1> 	xor	ch, ch
   755 000002AC 80E13F              <1> 	and	cl, 3Fh	; sectors (bits 0-6)
   756 000002AF 890F                <1> 	mov	[bx], cx
   757 000002B1 81EB[F065]          <1>         sub     bx, drv.spt
   758 000002B5 D1E3                <1> 	shl	bx, 1
   759 000002B7 81C3[FE65]          <1> 	add	bx, drv.size ; disk size (in sectors)
   760                              <1> 	; LBA size = cylinders * heads * secpertrack
   761 000002BB F7E1                <1> 	mul	cx 
   762 000002BD 89C2                <1> 	mov	dx, ax	; heads*spt					
   763 000002BF 58                  <1> 	pop	ax ; ** cylinders
   764 000002C0 48                  <1> 	dec	ax ; 1 cylinder reserved (!?)
   765 000002C1 F7E2                <1> 	mul	dx ; cylinders * (heads*spt)		
   766 000002C3 8907                <1> 	mov	[bx], ax
   767 000002C5 895702              <1> 	mov	[bx+2], dx
   768                              <1> 	;
   769                              <1> 	;pop	bx
   770 000002C8 C3                  <1> 	retn
   771                              <1> 
   772                              <1> ;align 2
   773                              <1> 
   774                              <1> ;cylinders :  dw 0, 0, 0, 0, 0, 0
   775                              <1> ;heads	  :  dw 0, 0, 0, 0, 0, 0
   776                              <1> ;spt	  :  dw 0, 0, 0, 0, 0, 0
   777                              <1> ;disk_size :  dd 0, 0, 0, 0, 0, 0
   778                              <1> 
   779                              <1> ;last_drv:
   780                              <1> ;	db  0
   781                              <1> ;drv_status:
   782                              <1> ;	db  0,0,0,0,0,0
   783                              <1> ;	db 0
   784                              <1> 
   785                              <1> ; End Of DISK I/O SYSTEM STRUCTURE INITIALIZATION /// 06/02/2015
   786                              <1> 
   787                              <1> L16:
   223                                  
   224                                  	; 10/11/2014
   225 000002C9 FA                           	cli	; Disable interrupts (clear interrupt flag)
   226                                  		; Reset Interrupt MASK Registers (Master&Slave)
   227                                  	;mov	al, 0FFh	; mask off all interrupts
   228                                  	;out	21h, al		; on master PIC (8259)
   229                                  	;jmp 	$+2  ; (delay)
   230                                  	;out	0A1h, al	; on slave PIC (8259)
   231                                  	;
   232                                  	; Disable NMI 
   233 000002CA B080                    	mov   	al, 80h 
   234 000002CC E670                    	out   	70h, al		; set bit 7 to 1 for disabling NMI
   235                                  	;23/02/2015
   236 000002CE 90                      	nop			;
   237                                  	;in	al, 71h		; read in 71h just after writing out to 70h
   238                                  				; for preventing unknown state (!?)
   239                                  
   240                                  	; 02/01/2022
   241                                  	%define KERNELFSIZE KEND-KSTART 
   242                                  	;
   243                                   	; 20/08/2014
   244                                  	; Moving the kernel 64 KB back (to physical address 0)
   245                                  	; DS = CS = 1000h
   246                                  	; 05/11/2014
   247 000002CF 31C0                    	xor	ax, ax
   248 000002D1 8EC0                    	mov	es, ax ; ES = 0
   249                                  	;
   250                                  	;;mov	cx, (KEND - KLOAD)/4
   251                                  	;mov	cx, (KERNELFSIZE+3)/4 ; 02/01/2022
   252 000002D3 B93634                  	mov	cx, (KERNELFSIZE+1)/2 ; 02/01/2022
   253 000002D6 31F6                    	xor	si, si
   254 000002D8 31FF                    	xor	di, di
   255                                  	;rep	movsd
   256 000002DA F3A5                    	rep	movsw ; 02/01/2022
   257                                  	;
   258 000002DC 06                      	push	es ; 0
   259 000002DD 68[E102]                	push	L17
   260 000002E0 CB                      	retf
   261                                  	;
   262                                  L17:
   263                                  	; Turn off the floppy drive motor
   264 000002E1 BAF203                          mov     dx, 3F2h
   265 000002E4 EE                              out     dx, al ; 0 ; 31/12/2013
   266                                  
   267                                  	; Enable access to memory above one megabyte
   268                                  L18:
   269 000002E5 E464                    	in	al, 64h
   270 000002E7 A802                    	test	al, 2
   271 000002E9 75FA                            jnz     short L18
   272 000002EB B0D1                    	mov	al, 0D1h	; Write output port
   273 000002ED E664                    	out	64h, al
   274                                  L19:
   275 000002EF E464                    	in	al, 64h
   276 000002F1 A802                    	test	al, 2
   277 000002F3 75FA                            jnz     short L19
   278 000002F5 B0DF                    	mov	al, 0DFh	; Enable A20 line
   279 000002F7 E660                    	out	60h, al
   280                                  ;L20:
   281                                  	;
   282                                  	; Load global descriptor table register
   283                                  
   284                                          ;mov     ax, cs
   285                                          ;mov     ds, ax
   286                                  
   287 000002F9 2E0F0116[F062]                  lgdt    [cs:gdtd]
   288                                  
   289 000002FF 0F20C0                          mov     eax, cr0
   290                                  	; or 	eax, 1
   291 00000302 40                      	inc     ax
   292 00000303 0F22C0                  	mov     cr0, eax
   293                                  
   294                                  	; Jump to 32 bit code
   295                                  	
   296 00000306 66                      	db 66h 			; Prefix for 32-bit
   297 00000307 EA                      	db 0EAh 		; Opcode for far jump
   298 00000308 [0E030000]              	dd StartPM 		; Offset to start, 32-bit
   299                                  				; (1000h:StartPM = StartPM + 10000h)
   300 0000030C 0800                    	dw KCODE		; This is the selector for CODE32_DESCRIPTOR,
   301                                  				; assuming that StartPM resides in code32
   302                                  
   303                                  [BITS 32] 
   304                                  
   305                                  StartPM:
   306                                  	; Kernel Base Address = 0 ; 30/12/2013
   307 0000030E 66B81000                	mov ax, KDATA           ; Save data segment identifier
   308 00000312 8ED8                            mov ds, ax              ; Move a valid data segment into DS register
   309 00000314 8EC0                           	mov es, ax              ; Move data segment into ES register
   310 00000316 8EE0                           	mov fs, ax              ; Move data segment into FS register
   311 00000318 8EE8                          	mov gs, ax              ; Move data segment into GS register
   312 0000031A 8ED0                            mov ss, ax              ; Move data segment into SS register
   313 0000031C BC00000900                      mov esp, 90000h         ; Move the stack pointer to 090000h
   314                                  
   315                                  clear_bss: ; Clear uninitialized data area
   316                                  	; 11/03/2015
   317 00000321 31C0                    	xor	eax, eax ; 0
   318                                  	;mov	ecx, (bss_end - bss_start)/4
   319                                  	;;shr	ecx, 2 ; bss section is already aligned for double words
   320                                  	; 02/01/2022
   321 00000323 B9BC050000              	mov	ecx, BSS_SIZE/4
   322 00000328 BF[70680000]            	mov	edi, bss_start
   323 0000032D F3AB                    	rep	stosd  		
   324                                  
   325                                  memory_init:
   326                                  	; Initialize memory allocation table and page tables
   327                                  	;
   328                                  	; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
   329                                  	; 16/11/2014
   330                                  	; 15/11/2014
   331                                  	; 07/11/2014
   332                                  	; 06/11/2014
   333                                  	; 05/11/2014
   334                                  	; 04/11/2014
   335                                  	; 31/10/2014 (Retro UNIX 386 v1 - Beginning) 
   336                                  	;
   337                                  ;	xor	eax, eax
   338                                  ;	xor 	ecx, ecx
   339 0000032F B108                    	mov	cl, 8
   340 00000331 BF00001000              	mov	edi, MEM_ALLOC_TBL	
   341 00000336 F3AB                    	rep	stosd		   ; clear Memory Allocation Table
   342                                  				   ; for the first 1 MB memory
   343                                  	;
   344 00000338 8B0D[64680000]          	mov	ecx, [mem_1m_1k]   ; 02/01/2022	
   345                                  	;mov	cx, [mem_1m_1k]	   ; Number of contiguous KB between
   346                                  				   ; 1 and 16 MB, max. 3C00h = 15 MB.
   347                                  	;shr	cx, 2		   ; convert 1 KB count to 4 KB count
   348 0000033E C1E902                  	shr	ecx, 2	; 02/01/2022
   349 00000341 890D[E06A0000]          	mov	[free_pages], ecx
   350 00000347 8B15[68680000]          	mov	edx, [mem_16m_64k] ; 02/01/2022
   351                                  	;mov	dx, [mem_16m_64k]  ; Number of contiguous 64 KB blocks
   352                                  				   ; between 16 MB and 4 GB.
   353                                  	;or	dx, dx
   354 0000034D 09D2                    	or	edx, edx ; 02/01/2022
   355 0000034F 7412                    	jz	short mi_0
   356                                  	;
   357                                  	;mov	ax, dx
   358 00000351 89D0                    	mov	eax, edx ; 02/01/2022
   359 00000353 C1E004                  	shl	eax, 4		   ; 64 KB -> 4 KB (page count)
   360 00000356 0105[E06A0000]          	add	[free_pages], eax
   361 0000035C 0500100000              	add	eax, 4096	   ; 16 MB = 4096 pages
   362 00000361 EB06                    	jmp	short mi_1
   363                                  mi_0:
   364                                  	;mov	ax, cx
   365 00000363 89C8                    	mov	eax, ecx ; 02/01/2022	 
   366 00000365 66050001                	add	ax, 256		   ; add 256 pages for the first 1 MB
   367                                  mi_1:
   368 00000369 A3[DC6A0000]            	mov	[memory_size], eax ; Total available memory in pages
   369                                  				   ; 1 alloc. tbl. bit = 1 memory page
   370                                  				   ; 32 allocation bits = 32 mem. pages
   371                                  	;
   372 0000036E 05FF7F0000              	add	eax, 32767	   ; 32768 memory pages per 1 M.A.T. page
   373 00000373 C1E80F                  	shr	eax, 15		   ; ((32768 * x) + y) pages (y < 32768)
   374                                  				   ;  --> x + 1 M.A.T. pages, if y > 0
   375                                  				   ;  --> x M.A.T. pages, if y = 0
   376                                  	;mov	[mat_size], ax	   ; Memory Alloc. Table Size in pages
   377 00000376 A3[F06A0000]            	mov	[mat_size], eax ; 02/01/2022
   378 0000037B C1E00C                  	shl	eax, 12		   ; 1 M.A.T. page = 4096 bytes
   379                                  	;			   ; Max. 32 M.A.T. pages (4 GB memory)
   380 0000037E 89C3                    	mov	ebx, eax	   ; M.A.T. size in bytes
   381                                  	; Set/Calculate Kernel's Page Directory Address
   382 00000380 81C300001000            	add	ebx, MEM_ALLOC_TBL
   383 00000386 891D[D86A0000]          	mov	[k_page_dir], ebx  ; Kernel's Page Directory address
   384                                  				   ; just after the last M.A.T. page
   385                                  	;
   386 0000038C 83E804                  	sub	eax, 4		   ; convert M.A.T. size to offset value
   387 0000038F A3[E86A0000]            	mov	[last_page], eax   ; last page ofset in the M.A.T.
   388                                  	;			   ; (allocation status search must be
   389                                  				   ; stopped after here)
   390 00000394 31C0                    	xor	eax, eax
   391 00000396 48                      	dec	eax		   ; FFFFFFFFh (set all bits to 1)
   392                                  	;push	cx
   393 00000397 51                      	push	ecx ; 02/01/2022 
   394 00000398 C1E905                  	shr	ecx, 5		   ; convert 1 - 16 MB page count to
   395                                  				   ; count of 32 allocation bits
   396 0000039B F3AB                    	rep	stosd
   397                                  	;pop	cx
   398 0000039D 59                      	pop	ecx ; 02/01/2022
   399 0000039E 40                      	inc	eax		   ; 0
   400 0000039F 80E11F                  	and	cl, 31		   ; remain bits
   401 000003A2 7412                    	jz	short mi_4
   402 000003A4 8907                    	mov	[edi], eax	   ; reset
   403                                  mi_2:
   404 000003A6 0FAB07                  	bts	[edi], eax	   ; 06/11/2014
   405 000003A9 FEC9                    	dec	cl
   406 000003AB 7404                    	jz	short mi_3
   407 000003AD FEC0                    	inc	al
   408 000003AF EBF5                    	jmp	short mi_2
   409                                  mi_3:
   410 000003B1 28C0                    	sub	al, al	   	   ; 0
   411 000003B3 83C704                  	add	edi, 4		   ; 15/11/2014
   412                                  mi_4:
   413 000003B6 09D2                    	or	edx, edx ; 02/01/2022
   414                                  	;or	dx, dx		  ; check 16M to 4G memory space
   415 000003B8 741F                    	jz	short mi_6	  ; max. 16 MB memory, no more...
   416                                  	;	
   417 000003BA B900021000              	mov	ecx, MEM_ALLOC_TBL + 512 ; End of first 16 MB memory
   418                                  	;	
   419 000003BF 29F9                    	sub	ecx, edi	  ; displacement (to end of 16 MB)
   420 000003C1 7405                    	jz	short mi_5	  ; jump if EDI points to 
   421                                  				  ;         end of first 16 MB	
   422                                  	;shr	ecx, 1		  ; convert to dword count
   423                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   424 000003C3 C1E902                  	shr	ecx, 2	; 02/01/2022
   425 000003C6 F3AB                    	rep 	stosd		  ; reset all bits for reserved pages
   426                                  				  ; (memory hole under 16 MB)
   427                                  mi_5:
   428 000003C8 89D1                    	mov	ecx, edx ; 02/01/2022
   429                                  	;mov	cx, dx		  ; count of 64 KB memory blocks
   430 000003CA D1E9                    	shr	ecx, 1		  ; 1 alloc. dword per 128 KB memory
   431 000003CC 9C                      	pushf			  ; 16/11/2014		
   432 000003CD 48                      	dec	eax		  ; FFFFFFFFh (set all bits to 1)
   433 000003CE F3AB                    	rep	stosd
   434 000003D0 40                      	inc	eax		  ; 0
   435 000003D1 9D                      	popf			  ; 16/11/2014
   436 000003D2 7305                    	jnc	short mi_6
   437 000003D4 6648                    	dec	ax		  ; eax = 0000FFFFh
   438 000003D6 AB                      	stosd
   439 000003D7 6640                    	inc	ax		  ; 0		
   440                                  mi_6:
   441 000003D9 39DF                    	cmp	edi, ebx	  ; check if EDI points to 	
   442 000003DB 7309                    	jnb	short mi_7	  ; end of memory allocation table
   443                                  	;			  ; (>= MEM_ALLOC_TBL + 4906) 
   444 000003DD 89D9                    	mov	ecx, ebx	  ; end of memory allocation table
   445 000003DF 29F9                    	sub	ecx, edi	  ; convert displacement/offset
   446                                  	;shr	ecx, 1		  ; to dword count
   447                                  	;shr	ecx, 1		  ; (shift 2 bits right) 
   448 000003E1 C1E902                  	shr	ecx, 2 ; 02/01/2022	
   449 000003E4 F3AB                    	rep 	stosd		  ; reset all remain M.A.T. bits
   450                                  mi_7:
   451                                  	; Reset M.A.T. bits in M.A.T. (allocate M.A.T. pages)
   452 000003E6 BA00001000              	mov	edx, MEM_ALLOC_TBL
   453                                  	;sub	ebx, edx	  ; Mem. Alloc. Tbl. size in bytes
   454                                  	;shr	ebx, 12		  ; Mem. Alloc. Tbl. size in pages	
   455 000003EB 8B0D[F06A0000]          	mov	ecx, [mat_size] ; 02/01/2022
   456                                  	;mov	cx, [mat_size]	  ; Mem. Alloc. Tbl. size in pages
   457 000003F1 89D7                    	mov	edi, edx
   458 000003F3 C1EF0F                  	shr	edi, 15		  ; convert M.A.T. address to
   459                                  				  ; byte offset in M.A.T.
   460                                  				  ; (1 M.A.T. byte points to 
   461                                  				  ;	      32768 bytes)
   462                                  				  ; Note: MEM_ALLOC_TBL address 
   463                                  				  ; must be aligned on 128 KB 
   464                                  				  ; boundary!
   465 000003F6 01D7                    	add	edi, edx	  ; points to M.A.T.'s itself	
   466                                  	; eax = 0
   467 000003F8 290D[E06A0000]          	sub	[free_pages], ecx ; 07/11/2014
   468                                  mi_8:
   469 000003FE 0FB307                  	btr	[edi], eax	  ; clear bit 0 to bit x (1 to 31)
   470                                  	;dec	bl
   471 00000401 FEC9                    	dec	cl
   472 00000403 7404                    	jz	short mi_9
   473 00000405 FEC0                    	inc	al
   474 00000407 EBF5                    	jmp	short mi_8
   475                                  mi_9:
   476                                  	;
   477                                  	; Reset Kernel's Page Dir. and Page Table bits in M.A.T.
   478                                  	;		(allocate pages for system page tables)
   479                                  
   480                                  	; edx = MEM_ALLOC_TBL
   481 00000409 8B0D[DC6A0000]          	mov	ecx, [memory_size] ; memory size in pages (PTEs)
   482 0000040F 81C1FF030000            	add	ecx, 1023	 ; round up (1024 PTEs per table)
   483 00000415 C1E90A                  	shr	ecx, 10		 ; convert memory page count to 
   484                                  				 ; page table count (PDE count)
   485                                  	;
   486 00000418 51                      	push	ecx		 ; (**) PDE count (<= 1024)
   487                                  	;
   488 00000419 41                      	inc	ecx		 ; +1 for kernel page directory	
   489                                  	;
   490 0000041A 290D[E06A0000]          	sub	[free_pages], ecx ; 07/11/2014
   491                                  	;
   492 00000420 8B35[D86A0000]          	mov	esi, [k_page_dir] ; Kernel's Page Directory address
   493 00000426 C1EE0C                  	shr	esi, 12		 ; convert to page number
   494                                  mi_10:
   495 00000429 89F0                    	mov	eax, esi	 ; allocation bit offset
   496 0000042B 89C3                    	mov	ebx, eax
   497 0000042D C1EB03                  	shr	ebx, 3		 ; convert to alloc. byte offset
   498 00000430 80E3FC                  	and	bl,  0FCh	 ; clear bit 0 and bit 1
   499                                  				 ;   to align on dword boundary
   500 00000433 83E01F                  	and	eax, 31		 ; set allocation bit position 
   501                                  				 ;  (bit 0 to bit 31)
   502                                  	;
   503 00000436 01D3                    	add	ebx, edx	 ; offset in M.A.T. + M.A.T. address 
   504                                  	;
   505 00000438 0FB303                  	btr 	[ebx], eax	 ; reset relevant bit (0 to 31)
   506                                  	;
   507 0000043B 46                      	inc	esi		 ; next page table
   508 0000043C E2EB                    	loop	mi_10		 ; allocate next kernel page table 
   509                                  				 ; (ecx = page table count + 1)
   510                                  	;
   511 0000043E 59                      	pop	ecx		 ; (**) PDE count (= pg. tbl. count)
   512                                  	;
   513                                  	; Initialize Kernel Page Directory and Kernel Page Tables
   514                                  	;
   515                                  	; Initialize Kernel's Page Directory
   516 0000043F 8B3D[D86A0000]          	mov	edi, [k_page_dir]
   517 00000445 89F8                    	mov	eax, edi
   518 00000447 0C03                    	or	al, PDE_A_PRESENT + PDE_A_WRITE
   519                                  		     	      ; supervisor + read&write + present
   520 00000449 89CA                    	mov	edx, ecx 	; (**) PDE count (= pg. tbl. count)
   521                                  mi_11:
   522 0000044B 0500100000              	add	eax, 4096	; Add page size (PGSZ)
   523                                  			        ; EAX points to next page table
   524 00000450 AB                      	stosd
   525 00000451 E2F8                    	loop	mi_11
   526 00000453 29C0                    	sub	eax, eax	; Empty PDE
   527                                  	;mov	cx, 1024	; Entry count (PGSZ/4)
   528                                  	; 02/01/2022
   529 00000455 B504                    	mov	ch, 4 ; cx = 4*256 = 1024
   530 00000457 29D1                    	sub	ecx, edx
   531 00000459 7402                    	jz	short mi_12
   532 0000045B F3AB                    	rep	stosd 		; clear remain (empty) PDEs
   533                                  	;
   534                                  	; Initialization of Kernel's Page Directory is OK, here.
   535                                  mi_12:
   536                                  	; Initialize Kernel's Page Tables
   537                                  	;
   538                                  	; (EDI points to address of page table 0)
   539                                  	; eax = 0
   540 0000045D 8B0D[DC6A0000]          	mov	ecx, [memory_size] ; memory size in pages
   541 00000463 89CA                    	mov	edx, ecx	; (***)
   542 00000465 B003                    	mov	al, PTE_A_PRESENT + PTE_A_WRITE
   543                                  			     ; supervisor + read&write + present
   544                                  mi_13:
   545 00000467 AB                      	stosd
   546 00000468 0500100000              	add	eax, 4096	
   547 0000046D E2F8                    	loop	mi_13
   548                                  	; 02/01/2022
   549 0000046F 66B9FF03                	mov	cx, 1023
   550 00000473 21CA                    	and	edx, ecx
   551                                  	;and	dx, 1023	; (***)
   552 00000475 7407                    	jz	short mi_14
   553                                  	;mov	cx, 1024	
   554                                  	; 02/01/2022
   555                                  	;mov	ch, 4 ; cx = 4*256 = 1024
   556 00000477 41                      	inc	ecx ; ecx = 1024
   557 00000478 29D1                    	sub	ecx, edx
   558                                  	;sub	cx, dx		; from dx (<= 1023) to 1024
   559 0000047A 31C0                    	xor	eax, eax
   560 0000047C F3AB                    	rep	stosd		; clear remain (empty) PTEs 
   561                                  				; of the last page table
   562                                  mi_14:
   563                                  	;  Initialization of Kernel's Page Tables is OK, here.
   564                                  	;
   565 0000047E 89F8                    	mov	eax, edi	; end of the last page table page
   566                                  			        ; (beginging of user space pages)
   567 00000480 C1E80F                  	shr	eax, 15		; convert to M.A.T. byte offset
   568 00000483 24FC                    	and	al, 0FCh	; clear bit 0 and bit 1 for
   569                                  				; aligning on dword boundary
   570                                  	 
   571 00000485 A3[EC6A0000]            	mov	[first_page], eax
   572 0000048A A3[E46A0000]            	mov	[next_page], eax ; The first free page pointer
   573                                  				 ; for user programs
   574                                  				 ; (Offset in Mem. Alloc. Tbl.)	
   575                                  	;
   576                                  	; Linear/FLAT (1 to 1) memory paging for the kernel is OK, here.
   577                                  	;
   578                                  	
   579                                  	; Enable paging
   580                                  	;
   581 0000048F A1[D86A0000]                    mov     eax, [k_page_dir]
   582 00000494 0F22D8                  	mov	cr3, eax
   583 00000497 0F20C0                  	mov	eax, cr0
   584 0000049A 0D00000080              	or	eax, 80000000h	; set paging bit (bit 31)
   585 0000049F 0F22C0                  	mov	cr0, eax
   586                                          ;jmp    KCODE:StartPMP
   587                                  
   588 000004A2 EA                      	db 0EAh 		; Opcode for far jump
   589 000004A3 [A9040000]                      dd StartPMP		; 32 bit offset
   590 000004A7 0800                    	dw KCODE		; kernel code segment descriptor
   591                                  
   592                                  StartPMP:
   593                                  	; 06/11//2014
   594                                  	; Clear video page 0
   595                                  	;
   596                                  	; Temporary Code
   597                                  	;
   598                                  	;mov	ecx, 80*25/2
   599 000004A9 66B9E803                	mov	cx, (80*25)/2 ; 02/01/2022
   600 000004AD BF00800B00              	mov	edi, 0B8000h
   601 000004B2 57                      	push	edi ; * ; 02/01/2022
   602 000004B3 31C0                    	xor	eax, eax	; black background, black fore color
   603 000004B5 F3AB                    	rep	stosd
   604                                  	
   605                                  	; 19/08/2014
   606                                  	; Kernel Base Address = 0
   607                                  	; It is mapped to (physically) 0 in the page table.
   608                                  	; So, here is exactly 'StartPMP' address.
   609                                  	;
   610                                  	;;mov	ah, 4Eh	; Red background, yellow forecolor
   611                                  	;;mov	esi, msgPM
   612                                  	;; 14/08/2015 (kernel version message will appear
   613                                  	;;	       when protected mode and paging is enabled)
   614 000004B7 B40B                    	mov	ah, 0Bh ; Black background, light cyan forecolor
   615 000004B9 BE[30660000]            	mov	esi, msgKVER
   616 000004BE 5F                      	pop	edi ; * ; 02/01/2022
   617                                  	;mov	edi, 0B8000h ; 27/08/2014
   618                                  	; 20/08/2014
   619 000004BF E892010000              	call	printk
   620                                  
   621                                  	; 'UNIX v7/x86' source code by Robert Nordier (1999)
   622                                  	; // Set IRQ offsets
   623                                  	;
   624                                  	;  Linux (v0.12) source code by Linus Torvalds (1991)
   625                                  	;
   626                                  					;; ICW1
   627 000004C4 B011                    	mov	al, 11h			; Initialization sequence
   628 000004C6 E620                    	out	20h, al			; 	8259A-1
   629                                  	; jmp 	$+2
   630 000004C8 E6A0                    	out	0A0h, al		; 	8259A-2
   631                                  					;; ICW2
   632 000004CA B020                    	mov	al, 20h			; Start of hardware ints (20h)
   633 000004CC E621                    	out	21h, al			;	for 8259A-1
   634                                  	; jmp 	$+2
   635 000004CE B028                    	mov	al, 28h			; Start of hardware ints (28h)
   636 000004D0 E6A1                    	out	0A1h, al		; 	for 8259A-2
   637                                  					;
   638 000004D2 B004                    	mov	al, 04h			;; ICW3
   639 000004D4 E621                    	out	21h, al			; 	IRQ2 of 8259A-1 (master)
   640                                  	; jmp 	$+2
   641 000004D6 B002                    	mov	al, 02h			; 	is 8259A-2 (slave)
   642 000004D8 E6A1                    	out	0A1h, al		;
   643                                  					;; ICW4
   644 000004DA B001                    	mov	al, 01h	 		;
   645 000004DC E621                    	out	21h, al			; 	8086 mode, normal EOI	
   646                                  	; jmp 	$+2
   647 000004DE E6A1                    	out	0A1h, al		;	for both chips.
   648                                  
   649                                  	;mov	al, 0FFh	; mask off all interrupts for now
   650                                  	;out	21h, al
   651                                  	;; jmp 	$+2
   652                                  	;out	0A1h, al
   653                                  
   654                                  	; 02/04/2015
   655                                  	; 26/03/2015 System call (INT 30h) modification
   656                                  	;  DPL = 3 (Interrupt service routine can be called from user mode)			
   657                                  	;
   658                                  	;; Linux (v0.12) source code by Linus Torvalds (1991)
   659                                  	;  setup_idt:
   660                                  	;
   661                                          ;; 16/02/2015
   662                                  	;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   663                                  	; 21/08/2014 (timer_int)
   664 000004E0 BE[FC620000]            	mov	esi, ilist
   665 000004E5 8D3D[70680000]          	lea	edi, [idt]
   666                                  	; 26/03/2015
   667 000004EB B930000000              	mov	ecx, 48		; 48 hardware interrupts (INT 0 to INT 2Fh)
   668                                  	; 02/04/2015
   669 000004F0 BB00000800              	mov	ebx,  80000h
   670                                  rp_sidt1:
   671 000004F5 AD                      	lodsd
   672 000004F6 89C2                    	mov	edx, eax
   673 000004F8 66BA008E                	mov	dx, 8E00h
   674 000004FC 6689C3                  	mov	bx, ax
   675 000004FF 89D8                    	mov	eax, ebx	; /* selector = 0x0008 = cs */
   676                                         			        ; /* interrupt gate - dpl=0, present */
   677 00000501 AB                      	stosd	; selector & offset bits 0-15 	
   678 00000502 89D0                    	mov	eax, edx
   679 00000504 AB                      	stosd	; attributes & offset bits 16-23
   680 00000505 E2EE                    	loop	rp_sidt1
   681 00000507 B110                    	mov	cl, 16        ; 16 software interrupts (INT 30h to INT 3Fh)
   682                                  rp_sidt2:
   683 00000509 AD                      	lodsd
   684 0000050A 21C0                    	and	eax, eax
   685 0000050C 7413                    	jz	short rp_sidt3
   686 0000050E 89C2                    	mov	edx, eax
   687 00000510 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   688 00000514 6689C3                  	mov	bx, ax
   689 00000517 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   690 00000519 AB                      	stosd
   691 0000051A 89D0                    	mov	eax, edx
   692 0000051C AB                      	stosd
   693 0000051D E2EA                    	loop	rp_sidt2
   694 0000051F EB16                    	jmp	short sidt_OK
   695                                  rp_sidt3:
   696 00000521 B8[7A090000]            	mov	eax, ignore_int
   697 00000526 89C2                    	mov	edx, eax
   698 00000528 66BA00EE                	mov	dx, 0EE00h	; P=1b/DPL=11b/01110b
   699 0000052C 6689C3                  	mov	bx, ax
   700 0000052F 89D8                    	mov	eax, ebx	; selector & offset bits 0-15 	
   701                                  rp_sidt4:
   702 00000531 AB                      	stosd
   703 00000532 92                      	xchg	eax, edx
   704 00000533 AB                      	stosd
   705 00000534 92                      	xchg	edx, eax
   706 00000535 E2FA                    	loop	rp_sidt4
   707                                  sidt_OK: 
   708 00000537 0F011D[F6620000]        	lidt 	[idtd]
   709                                  	;
   710                                  	; TSS descriptor setup ; 24/03/2015
   711 0000053E B8[706A0000]            	mov	eax, task_state_segment
   712 00000543 66A3[EA620000]          	mov	[gdt_tss0], ax
   713 00000549 C1C010                  	rol	eax, 16
   714 0000054C A2[EC620000]            	mov	[gdt_tss1], al
   715 00000551 8825[EF620000]          	mov	[gdt_tss2], ah
   716 00000557 66C705[D66A0000]68-     	mov	word [tss.IOPB], tss_end - task_state_segment
   716 0000055F 00                 
   717                                  		; 
   718                                  		; IO Map Base address (When this address points
   719                                  		; to end of the TSS, CPU does not use IO port 
   720                                  		; permission bit map for RING 3 IO permissions, 
   721                                  		; access to any IO ports in ring 3 will be forbidden.)
   722                                   		;
   723                                  	;mov	[tss.esp0], esp ; TSS offset 4
   724                                  	;mov	word [tss.ss0], KDATA ; TSS offset 8 (SS)
   725 00000560 66B82800                   	mov	ax, TSS  ; It is needed when an interrupt 
   726                                  			 ; occurs (or a system call -software INT- is requested)
   727                                  			 ; while cpu running in ring 3 (in user mode).				
   728                                  			 ; (Kernel stack pointer and segment will be loaded
   729                                  			 ; from offset 4 and 8 of the TSS, by the CPU.)	 
   730 00000564 0F00D8                  	ltr	ax  ; Load task register
   731                                  	;
   732                                  esp0_set0:
   733                                  	; 30/07/2015
   734 00000567 8B0D[DC6A0000]          	mov 	ecx, [memory_size] ; memory size in pages
   735 0000056D C1E10C                  	shl 	ecx, 12 ; convert page count to byte count
   736 00000570 81F900004000            	cmp	ecx, CORE ; beginning of user's memory space (400000h)
   737                                  			  ; (kernel mode virtual address)
   738 00000576 7605                    	jna	short esp0_set1
   739                                  	;
   740                                  	; If available memory > CORE (end of the 1st 4 MB)
   741                                  	; set stack pointer to CORE
   742                                  	;(Because, PDE 0 is reserved for kernel space in user's page directory)
   743                                  	;(PDE 0 points to page table of the 1st 4 MB virtual address space)
   744 00000578 B900004000              	mov	ecx, CORE
   745                                  esp0_set1:
   746 0000057D 89CC                    	mov	esp, ecx ; top of kernel stack (**tss.esp0**)
   747                                  esp0_set_ok:
   748                                  	; 30/07/2015 (**tss.esp0**) 
   749 0000057F 8925[746A0000]          	mov	[tss.esp0], esp
   750 00000585 66C705[786A0000]10-             mov     word [tss.ss0], KDATA
   750 0000058D 00                 
   751                                  	; 14/08/2015
   752                                  	; 10/11/2014 (Retro UNIX 386 v1 - Erdogan Tan)
   753                                  	;
   754                                  	;cli	; Disable interrupts (for CPU)
   755                                  	;    (CPU will not handle hardware interrupts, except NMI!)
   756                                  	;
   757 0000058E 30C0                    	xor	al, al		; Enable all hardware interrupts!
   758 00000590 E621                    	out	21h, al		; (IBM PC-AT compatibility)
   759 00000592 EB00                    	jmp 	$+2		; (All conventional PC-AT hardware
   760 00000594 E6A1                    	out	0A1h, al	;  interrupts will be in use.)	
   761                                  				; (Even if related hardware component
   762                                  				;  does not exist!)
   763                                  	; Enable NMI 
   764 00000596 B07F                    	mov	al, 7Fh		; Clear bit 7 to enable NMI (again)
   765 00000598 E670                    	out  	70h, al
   766                                  	; 23/02/2015
   767 0000059A 90                      	nop
   768 0000059B E471                    	in	al, 71h		; read in 71h just after writing out to 70h
   769                                  				; for preventing unknown state (!?)
   770                                  	;
   771                                  	; Only a NMI can occur here... (Before a 'STI' instruction)
   772                                  	;
   773                                  	; 02/09/2014
   774                                  	;xor	bx, bx
   775                                  	;mov	dx, 0200h	; Row 2, column 0  ; 07/03/2015
   776                                  	; 27/02/2022	
   777 0000059D 31DB                    	xor	ebx, ebx
   778 0000059F 31D2                    	xor	edx, edx
   779 000005A1 B602                    	mov	dh, 2
   780 000005A3 E8280F0000              	call	set_cpos
   781                                  	;
   782                                  	; 06/11/2014
   783                                  	; Temporary Code
   784                                  	;
   785 000005A8 E8A1100000              	call	memory_info
   786                                  	; 14/08/2015
   787                                  	;call getch ; 28/02/2015
   788                                  drv_init:
   789 000005AD FB                      	sti	; Enable Interrupts 
   790                                  	; 06/02/2015
   791 000005AE 8B15[D0650000]          	mov	edx, [hd0_type] ; hd0, hd1, hd2, hd3
   792 000005B4 668B1D[CE650000]        	mov	bx, [fd0_type] ; fd0, fd1
   793                                  	; 22/02/2015
   794 000005BB 6621DB                  	and	bx, bx
   795 000005BE 751B                    	jnz	short di1
   796                                  	;
   797 000005C0 09D2                    	or 	edx, edx
   798 000005C2 7529                    	jnz	short di2
   799                                  	;
   800                                  setup_error:
   801 000005C4 BE[19670000]            	mov 	esi, setup_error_msg
   802                                  psem:	
   803 000005C9 AC                      	lodsb
   804 000005CA 08C0                    	or	al, al
   805                                  	;jz	short haltx ; 22/02/2015
   806 000005CC 7426                    	jz	short di3
   807 000005CE 56                      	push	esi
   808 000005CF 31DB                    	xor	ebx, ebx ; 0
   809                                  			; Video page 0 (bl=0)
   810 000005D1 B407                    	mov	ah, 07h ; Black background, 
   811                                  			; light gray forecolor
   812 000005D3 E8EE0D0000              	call	write_tty
   813 000005D8 5E                      	pop	esi
   814 000005D9 EBEE                    	jmp	short psem
   815                                  
   816                                  di1:
   817                                  	; supress 'jmp short T6'
   818                                  	;  (activate fdc motor control code)
   819 000005DB 66C705[D7060000]90-     	mov	word [T5], 9090h ; nop
   819 000005E3 90                 
   820                                  	;
   821                                  	;mov	ax, int_0Eh	; IRQ 6 handler
   822                                  	;mov	di, 0Eh*4	; IRQ 6 vector
   823                                  	;stosw
   824                                  	;mov 	ax, cs
   825                                  	;stosw
   826                                  	;; 16/02/2015
   827                                          ;;mov	dword [DISKETTE_INT], fdc_int ; IRQ 6 handler
   828                                  	;
   829 000005E4 E8761F0000              	CALL	DSKETTE_SETUP	; Initialize Floppy Disks
   830                                  	;
   831 000005E9 09D2                    	or	edx, edx
   832 000005EB 7407                            jz      short di3
   833                                  di2:
   834 000005ED E8B21F0000              	call   	DISK_SETUP	; Initialize Fixed Disks
   835 000005F2 72D0                            jc      short setup_error
   836                                  di3:
   837 000005F4 E829100000              	call	setup_rtc_int	; 22/05/2015 (dsectrpm.s)
   838                                  	;
   839 000005F9 E8205C0000              	call	display_disks ; 07/03/2015  (Temporary)
   840                                  ;haltx:
   841                                  	; 14/08/2015
   842                                  	;call	getch ; 22/02/2015
   843 000005FE FB                      	sti	; Enable interrupts (for CPU)
   844                                  	; 14/08/2015
   845                                  	;mov 	ecx, 0FFFFFFFh
   846                                  	; 24/12/2021
   847 000005FF B9FFFF2F00              	mov 	ecx, 02FFFFFh
   848                                  md_info_msg_wait:
   849 00000604 51                      	push 	ecx
   850 00000605 B001                    	mov	al, 1
   851 00000607 8A25[066B0000]          	mov 	ah, [ptty] ; active (current) video page
   852 0000060D E86B590000              	call	getc_n
   853 00000612 59                      	pop	ecx
   854 00000613 7502                    	jnz	short md_info_msg_ok
   855 00000615 E2ED                    	loop	md_info_msg_wait
   856                                  md_info_msg_ok:
   857                                  	; 30/06/2015
   858 00000617 E8932C0000              	call	sys_init
   859                                  	;
   860                                  	;jmp 	cpu_reset ; 22/02/2015
   861                                  hang:
   862                                  	; 24/12/2021
   863 0000061C 29C0                    	sub	eax, eax
   864                                  _hang:	
   865                                  	; 23/02/2015
   866                                  	;sti			; Enable interrupts
   867 0000061E F4                      	hlt
   868                                  	;
   869                                  	;nop
   870                                  	;; 03/12/2014
   871                                  	;; 28/08/2014
   872                                  	;mov	ah, 11h
   873                                  	;call	getc
   874                                  	;jz      _c8
   875                                  	;
   876                                  	; 23/02/2015
   877                                  	; 06/02/2015
   878                                  	; 07/09/2014
   879 0000061F 31DB                    	xor	ebx, ebx
   880 00000621 8A1D[066B0000]          	mov	bl, [ptty]	; active_page
   881 00000627 89DE                    	mov	esi, ebx
   882 00000629 66D1E6                  	shl 	si, 1
   883 0000062C 81C6[086B0000]          	add	esi, ttychr
   884 00000632 668B06                  	mov	ax, [esi]
   885                                  	;and	ax, ax
   886                                  	;;jz	short _c8
   887                                  	;jz	short hang
   888                                  	; 24/12/2021
   889 00000635 21C0                    	and	eax, eax
   890 00000637 74E5                    	jz	short _hang
   891 00000639 66C7060000              	mov	word [esi], 0
   892 0000063E 80FB03                  	cmp	bl, 3		; Video page 3
   893                                  	;jb	short _c8
   894 00000641 72D9                    	jb	short hang
   895                                  	;	
   896                                  	; 02/09/2014
   897 00000643 B40E                    	mov	ah, 0Eh		; Yellow character 
   898                                  				; on black background
   899                                  	; 24/12/2021 (32 bit reg push-pop)
   900                                  	; 07/09/2014
   901                                  nxtl:
   902 00000645 53                      	push	ebx
   903                                  	;
   904                                  	;xor	ebx, ebx	; bl = 0 (video page 0)
   905                                  				; bh = 0 (video mode)
   906                                  				; Retro UNIX 386 v1 - Video Mode 0
   907                                  				; (PC/AT Video Mode 3 - 80x25 Alpha.)
   908 00000646 50                      	push	eax
   909 00000647 E87A0D0000              	call 	write_tty
   910 0000064C 58                      	pop	eax
   911                                  	;pop	bx
   912 0000064D 5B                      	pop	ebx
   913 0000064E 3C0D                    	cmp	al, 0Dh		; carriage return (enter)
   914                                  	;jne	short _c8
   915 00000650 75CA                    	jne	short hang
   916 00000652 B00A                    	mov	al, 0Ah		; next line
   917 00000654 EBEF                    	jmp	short nxtl
   918                                  	
   919                                  ;_c8:
   920                                  ;	; 25/08/2014
   921                                  ;	cli			; Disable interrupts
   922                                  ;	mov	al, [scounter + 1]
   923                                  ;	and	al, al
   924                                  ;	jnz	hang
   925                                  ;	call	rtc_p
   926                                  ;	jmp     hang
   927                                  
   928                                  
   929                                  	; 27/08/2014
   930                                  	; 20/08/2014
   931                                  printk:
   932                                          ;mov    edi, [scr_row]
   933                                  pkl:
   934 00000656 AC                      	lodsb
   935 00000657 08C0                    	or 	al, al
   936 00000659 7404                    	jz	short pkr
   937 0000065B 66AB                    	stosw
   938 0000065D EBF7                    	jmp	short pkl
   939                                  pkr:
   940 0000065F C3                      	retn
   941                                  
   942                                  ; 25/07/2015
   943                                  ; 14/05/2015 (multi tasking -time sharing- 'clock', x_timer)
   944                                  ; 17/02/2015
   945                                  ; 06/02/2015 (unix386.s)
   946                                  ; 11/12/2014 - 22/12/2014 (dsectrm2.s) 
   947                                  ;
   948                                  ; IBM PC-XT Model 286 Source Code - BIOS2.ASM (06/10/85)
   949                                  ;
   950                                  ;-- HARDWARE INT  08 H - ( IRQ LEVEL 0 ) ---------------------------------------
   951                                  ;	THIS ROUTINE HANDLES THE TIMER INTERRUPT FROM FROM CHANNEL 0 OF        :
   952                                  ;	THE 8254 TIMER.  INPUT FREQUENCY IS 1.19318 MHZ AND THE DIVISOR        :
   953                                  ;	IS 65536, RESULTING IN APPROXIMATELY 18.2 INTERRUPTS EVERY SECOND.     :
   954                                  ;									       :
   955                                  ;	THE INTERRUPT HANDLER MAINTAINS A COUNT (40:6C) OF INTERRUPTS SINCE    :
   956                                  ;	POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.	       :
   957                                  ;	THE INTERRUPT HANDLER ALSO DECREMENTS THE MOTOR CONTROL COUNT (40:40)  :
   958                                  ;	OF THE DISKETTE, AND WHEN IT EXPIRES, WILL TURN OFF THE 	       :
   959                                  ;	DISKETTE MOTOR(s), AND RESET THE MOTOR RUNNING FLAGS.		       :
   960                                  ;	THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH	       :
   961                                  ;	INTERRUPT 1CH AT EVERY TIME TICK.  THE USER MUST CODE A 	       :
   962                                  ;	ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.	       :
   963                                  ;-------------------------------------------------------------------------------
   964                                  ;
   965                                  
   966                                  timer_int:	; IRQ 0
   967                                  ;int_08h:	; Timer
   968                                  	; 14/10/2015
   969                                  	; Here, we are simulating system call entry (for task switch)
   970                                  	; (If multitasking is enabled, 
   971                                  	; 'clock' procedure may jump to 'sysrelease')
   972 00000660 1E                      	push	ds
   973 00000661 06                      	push	es
   974 00000662 0FA0                    	push	fs
   975 00000664 0FA8                    	push	gs
   976 00000666 60                      	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
   977 00000667 66B91000                	mov     cx, KDATA
   978 0000066B 8ED9                            mov     ds, cx
   979 0000066D 8EC1                            mov     es, cx
   980 0000066F 8EE1                            mov     fs, cx
   981 00000671 8EE9                            mov     gs, cx
   982                                  	;
   983 00000673 0F20D9                  	mov	ecx, cr3
   984 00000676 890D[19070000]          	mov	[cr3reg], ecx ; save current cr3 register value/content
   985                                  	;
   986 0000067C 3B0D[D86A0000]          	cmp 	ecx, [k_page_dir]
   987 00000682 741F                    	je	short T3
   988                                  	;
   989                                  	; timer interrupt has been occurred while OS is in user mode
   990 00000684 A3[986E0000]            	mov 	[u.r0], eax
   991 00000689 89E1                    	mov	ecx, esp
   992 0000068B 83C130                  	add	ecx, ESPACE ; 4 * 12 (stack frame)	
   993 0000068E 890D[906E0000]          	mov	[u.sp], ecx ; kernel stack pointer at the start of interrupt
   994 00000694 8925[946E0000]          	mov	[u.usp], esp ; kernel stack points to user's registers   
   995                                  	;
   996 0000069A 8B0D[D86A0000]          	mov	ecx, [k_page_dir]
   997 000006A0 0F22D9                  	mov	cr3, ecx
   998                                  T3:
   999 000006A3 FB                      	sti				; INTERRUPTS BACK ON
  1000 000006A4 66FF05[546B0000]        	INC	word [TIMER_LOW]	; INCREMENT TIME
  1001 000006AB 7507                    	JNZ	short T4		; GO TO TEST_DAY
  1002 000006AD 66FF05[566B0000]        	INC	word [TIMER_HIGH]	; INCREMENT HIGH WORD OF TIME
  1003                                  T4:					; TEST_DAY
  1004 000006B4 66833D[566B0000]18      	CMP	word [TIMER_HIGH],018H	; TEST FOR COUNT EQUALING 24 HOURS
  1005 000006BC 7519                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1006 000006BE 66813D[546B0000]B0-     	CMP	word [TIMER_LOW],0B0H
  1006 000006C6 00                 
  1007 000006C7 750E                    	JNZ	short T5		; GO TO DISKETTE_CTL
  1008                                  
  1009                                  ;-----	TIMER HAS GONE 24 HOURS
  1010                                  	;;SUB	AX,AX
  1011                                  	;MOV	[TIMER_HIGH],AX
  1012                                  	;MOV	[TIMER_LOW],AX
  1013 000006C9 29C0                    	sub	eax, eax
  1014 000006CB A3[546B0000]            	mov	[TIMER_LH], eax
  1015                                  	;	
  1016 000006D0 C605[586B0000]01        	MOV	byte [TIMER_OFL],1
  1017                                  
  1018                                  ;-----	TEST FOR DISKETTE TIME OUT
  1019                                  
  1020                                  T5:
  1021                                  	; 23/12/2014
  1022 000006D7 EB1D                    	jmp	short T6		; will be replaced with nop, nop
  1023                                  					; (9090h) if a floppy disk
  1024                                  					; is detected.
  1025                                  	;mov	al,[CS:MOTOR_COUNT]
  1026 000006D9 A0[5B6B0000]            	mov	al, [MOTOR_COUNT]
  1027 000006DE FEC8                    	dec	al
  1028                                  	;mov	[CS:MOTOR_COUNT], al	; DECREMENT DISKETTE MOTOR CONTROL
  1029 000006E0 A2[5B6B0000]            	mov	[MOTOR_COUNT], al
  1030                                  	;mov	[ORG_MOTOR_COUNT], al
  1031 000006E5 750F                    	JNZ	short T6		; RETURN IF COUNT NOT OUT
  1032 000006E7 B0F0                    	mov 	al,0F0h
  1033                                  	;AND	[CS:MOTOR_STATUS],al 	; TURN OFF MOTOR RUNNING BITS
  1034 000006E9 2005[5A6B0000]          	and	[MOTOR_STATUS], al
  1035                                  	;and	[ORG_MOTOR_STATUS], al
  1036 000006EF B00C                    	MOV	AL,0CH			; bit 3 = enable IRQ & DMA, 
  1037                                  					; bit 2 = enable controller
  1038                                  					;	1 = normal operation
  1039                                  					;	0 = reset	
  1040                                  					; bit 0, 1 = drive select
  1041                                  					; bit 4-7 = motor running bits 
  1042 000006F1 66BAF203                	MOV	DX,03F2H		; FDC CTL PORT
  1043 000006F5 EE                      	OUT	DX,AL			; TURN OFF THE MOTOR
  1044                                  T6:	
  1045                                  	;inc	word [CS:wait_count]	; 22/12/2014 (byte -> word)
  1046                                  					; TIMER TICK INTERRUPT
  1047                                  	;;inc	word [wait_count] ;;27/02/2015
  1048                                  	;INT	1CH			; TRANSFER CONTROL TO A USER ROUTINE
  1049                                  	;;;;cli
  1050                                  	;call 	u_timer			; TRANSFER CONTROL TO A USER ROUTINE
  1051 000006F6 FF15[11070000]          	call	[x_timer] ; 14/05/2015
  1052                                  T7:
  1053                                  	; 14/10/2015
  1054 000006FC B020                    	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  1055 000006FE FA                      	CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  1056 000006FF E620                    	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  1057                                  	;
  1058 00000701 A1[19070000]            	mov 	eax, [cr3reg] 		; previous value/content of cr3 register
  1059 00000706 0F22D8                   	mov	cr3, eax  ; restore cr3 register content
  1060                                  	;
  1061 00000709 61                      	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  1062                                  	;
  1063 0000070A 0FA9                    	pop	gs
  1064 0000070C 0FA1                    	pop	fs
  1065 0000070E 07                      	pop	es
  1066 0000070F 1F                      	pop	ds
  1067 00000710 CF                      	iretd	; return from interrupt
  1068                                  
  1069                                  
  1070                                  ; ////////////////
  1071                                  
  1072                                  ; 14/05/2015 - Multi tasking 'clock' procedure (sys emt)
  1073                                  x_timer:
  1074 00000711 [1D070000]              	dd 	u_timer			; 14/05/2015
  1075                                  	;dd	clock
  1076                                  
  1077                                  ; 26/02/2022 - Real time clock (digital) output demo (sys emt)
  1078                                  x_rtci:
  1079 00000715 [530A0000]              	dd	rtc_p	; (temporary demo code)	; 26/02/2022
  1080                                  
  1081                                  ; 14/10/2015
  1082 00000719 00000000                cr3reg: dd 0
  1083                                  
  1084                                  	; 24/12/2021 - Retro UNIX 386 v1.1
  1085                                  	; 06/02/2015
  1086                                  	; 07/09/2014
  1087                                  	; 21/08/2014
  1088                                  u_timer:
  1089                                  ;timer_int:	; IRQ 0
  1090                                  	; 06/02/2015
  1091                                  	;push	eax
  1092                                  	;push	edx
  1093                                  	;push	ecx
  1094                                  	;push	ebx
  1095                                  	;push	ds
  1096                                  	;push	es
  1097                                  	;mov	eax, KDATA
  1098                                  	;mov	ds, ax
  1099                                  	;mov	es, ax
  1100 0000071D FF05[1C6B0000]          	inc	dword [tcount]
  1101 00000723 BB[A2660000]            	mov	ebx, tcountstr + 4
  1102                                  	;mov	ax, [tcount]
  1103                                  	; 24/12/2021
  1104 00000728 A1[1C6B0000]            	mov	eax, [tcount]
  1105 0000072D B90A000000              	mov	ecx, 10
  1106                                  rp_divtcnt:
  1107 00000732 31D2                    	xor	edx, edx
  1108 00000734 F7F1                    	div	ecx
  1109 00000736 80C230                  	add	dl, 30h
  1110 00000739 8813                    	mov	[ebx], dl
  1111                                  	;or	ax, ax
  1112                                  	; 24/12/2021
  1113 0000073B 09C0                    	or	eax, eax
  1114 0000073D 7403                    	jz	short print_lzero
  1115 0000073F 4B                      	dec	ebx
  1116 00000740 EBF0                    	jmp	short rp_divtcnt
  1117                                  print_lzero:
  1118 00000742 81FB[9E660000]          	cmp	ebx, tcountstr
  1119 00000748 7606                    	jna	short print_tcount
  1120 0000074A 4B                      	dec	ebx
  1121 0000074B C60330                   	mov	byte [ebx], 30h
  1122 0000074E EBF2                    	jmp	short print_lzero
  1123                                  print_tcount:
  1124 00000750 56                      	push	esi
  1125 00000751 57                      	push	edi
  1126 00000752 BE[7A660000]            	mov	esi, timer_msg ; Timer interrupt message
  1127                                  	; 07/09/2014
  1128                                  	;mov	bx, 1	; Video page 1
  1129                                  	; 24/12/2021
  1130 00000757 29DB                    	sub	ebx, ebx
  1131                                  	;inc	bl ; ebx = 1
  1132                                  	; 02/01/2022
  1133 00000759 B306                    	mov	bl, 6	; Video page 6
  1134                                  ptmsg:
  1135 0000075B AC                      	lodsb
  1136 0000075C 08C0                    	or	al, al
  1137 0000075E 740D                    	jz	short ptmsg_ok
  1138 00000760 56                      	push	esi
  1139                                  	;push	bx
  1140                                  	; 24/12/2021
  1141 00000761 53                              push	ebx
  1142 00000762 B42F                    	mov     ah, 2Fh ; Green background, white forecolor
  1143 00000764 E85D0C0000              	call 	write_tty
  1144                                  	;pop	bx
  1145                                  	; 24/12/2021
  1146 00000769 5B                      	pop	ebx
  1147 0000076A 5E                      	pop	esi
  1148 0000076B EBEE                    	jmp	short ptmsg
  1149                                  	;; 27/08/2014
  1150                                  	;mov	edi, 0B8000h + 0A0h ; Row 1
  1151                                  	;call	printk
  1152                                  	;
  1153                                  ptmsg_ok:
  1154                                  	; 07/09/2014
  1155                                  	;xor	dx, dx		; column 0, row 0
  1156                                  	; 24/12/2021
  1157 0000076D 31D2                    	xor	edx, edx
  1158 0000076F E85C0D0000              	call	set_cpos	; set cursor position to 0,0 
  1159                                  	; 23/02/2015
  1160                                  	; 25/08/2014
  1161                                  	;mov	ebx, scounter		; (seconds counter)
  1162                                  	;dec	byte [ebx+1]		; (for reading real time clock)
  1163                                  ;	dec	byte [scounter+1]
  1164                                  ;;	jns	short timer_eoi		; 0 -> 0FFh ?
  1165                                  ;	jns	short u_timer_retn
  1166                                  	; 26/02/2015
  1167                                  ;	call	rtc_p
  1168                                  ;	mov	ebx, scounter		; (seconds counter)
  1169                                  ;	mov	byte [ebx+1], 18	; (18.2 timer ticks per second)
  1170                                  ;	dec 	byte [ebx]		; 19+18+18+18+18 (5)	
  1171                                  ;	jnz	short timer_eoi		; (109 timer ticks in 5 seconds)
  1172                                  ;	jnz	short u_timer_retn ; 06/02/2015
  1173                                  ;	mov	byte [ebx], 5
  1174                                  ;	inc	byte [ebx+1] ; 19
  1175                                  ;;timer_eoi:
  1176                                  ;;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1177                                  ;;	out	20h, al	; 8259 PORT
  1178                                  	;
  1179                                  ;u_timer_retn:  ; 06/02/2015
  1180 00000774 5F                      	pop	edi
  1181 00000775 5E                      	pop	esi
  1182                                  	;pop	es
  1183                                  	;pop	ds
  1184                                  	;pop	ebx
  1185                                  	;pop	ecx
  1186                                  	;pop	edx
  1187                                  	;pop	eax
  1188                                  	;iret
  1189 00000776 C3                      	retn	; 06/02/2015
  1190                                  
  1191                                  	; 28/08/2014
  1192                                  irq0:
  1193 00000777 6A00                            push 	dword 0
  1194 00000779 EB48                    	jmp	short which_irq
  1195                                  irq1:
  1196 0000077B 6A01                            push 	dword 1
  1197 0000077D EB44                    	jmp	short which_irq
  1198                                  irq2:
  1199 0000077F 6A02                            push 	dword 2
  1200 00000781 EB40                    	jmp	short which_irq
  1201                                  irq3:
  1202                                  	; 20/11/2015
  1203                                  	; 24/10/2015
  1204 00000783 2EFF15[D5390000]        	call	dword [cs:com2_irq3]
  1205 0000078A 6A03                    	push 	dword 3
  1206 0000078C EB35                    	jmp	short which_irq
  1207                                  irq4:
  1208                                  	; 20/11/2015
  1209                                  	; 24/10/2015
  1210 0000078E 2EFF15[D1390000]        	call	dword [cs:com1_irq4]
  1211 00000795 6A04                            push 	dword 4
  1212 00000797 EB2A                    	jmp	short which_irq
  1213                                  irq5:
  1214 00000799 6A05                            push 	dword 5
  1215 0000079B EB26                    	jmp	short which_irq
  1216                                  irq6:
  1217 0000079D 6A06                            push 	dword 6
  1218 0000079F EB22                    	jmp	short which_irq
  1219                                  irq7:
  1220 000007A1 6A07                            push 	dword 7
  1221 000007A3 EB1E                    	jmp	short which_irq
  1222                                  irq8:
  1223 000007A5 6A08                            push 	dword 8
  1224 000007A7 EB1A                    	jmp	short which_irq
  1225                                  irq9:
  1226 000007A9 6A09                            push 	dword 9
  1227 000007AB EB16                    	jmp	short which_irq
  1228                                  irq10:
  1229 000007AD 6A0A                            push 	dword 10
  1230 000007AF EB12                    	jmp	short which_irq
  1231                                  irq11:
  1232 000007B1 6A0B                            push 	dword 11
  1233 000007B3 EB0E                    	jmp	short which_irq
  1234                                  irq12:
  1235 000007B5 6A0C                            push 	dword 12
  1236 000007B7 EB0A                    	jmp	short which_irq
  1237                                  irq13:
  1238 000007B9 6A0D                            push 	dword 13
  1239 000007BB EB06                    	jmp	short which_irq
  1240                                  irq14:
  1241 000007BD 6A0E                            push 	dword 14
  1242 000007BF EB02                    	jmp	short which_irq
  1243                                  irq15:
  1244 000007C1 6A0F                            push 	dword 15
  1245                                  	;jmp	short which_irq
  1246                                  
  1247                                  	; 19/10/2015
  1248                                  	; 29/08/2014
  1249                                  	; 21/08/2014
  1250                                  which_irq:
  1251 000007C3 870424                  	xchg	eax, [esp]  ; 28/08/2014
  1252 000007C6 53                      	push	ebx
  1253 000007C7 56                      	push	esi
  1254 000007C8 57                      	push	edi
  1255 000007C9 1E                      	push 	ds
  1256 000007CA 06                      	push 	es
  1257                                  	;
  1258 000007CB 88C3                    	mov	bl, al
  1259                                  	;
  1260 000007CD B810000000              	mov	eax, KDATA
  1261 000007D2 8ED8                    	mov	ds, ax
  1262 000007D4 8EC0                    	mov	es, ax
  1263                                  	; 19/10/2015
  1264 000007D6 FC                      	cld
  1265                                          ; 27/08/2014
  1266 000007D7 8105[28660000]A000-             add     dword [scr_row], 0A0h
  1266 000007DF 0000               
  1267                                  	;
  1268 000007E1 B417                    	mov	ah, 17h	; blue (1) background, 
  1269                                  			; light gray (7) forecolor
  1270 000007E3 8B3D[28660000]                  mov     edi, [scr_row]
  1271 000007E9 B049                    	mov	al, 'I'
  1272 000007EB 66AB                    	stosw
  1273 000007ED B052                    	mov	al, 'R'
  1274 000007EF 66AB                    	stosw
  1275 000007F1 B051                    	mov	al, 'Q'
  1276 000007F3 66AB                    	stosw
  1277 000007F5 B020                    	mov	al, ' '
  1278 000007F7 66AB                    	stosw
  1279 000007F9 88D8                    	mov	al, bl
  1280 000007FB 3C0A                    	cmp	al, 10
  1281 000007FD 7208                    	jb	short iix
  1282 000007FF B031                    	mov	al, '1'
  1283 00000801 66AB                    	stosw
  1284 00000803 88D8                    	mov	al, bl
  1285 00000805 2C0A                    	sub	al, 10
  1286                                  iix:
  1287 00000807 0430                    	add	al, '0'
  1288 00000809 66AB                    	stosw
  1289 0000080B B020                    	mov	al, ' '
  1290 0000080D 66AB                    	stosw
  1291 0000080F B021                    	mov	al, '!'
  1292 00000811 66AB                    	stosw
  1293 00000813 B020                    	mov	al, ' '
  1294 00000815 66AB                    	stosw
  1295                                  	; 23/02/2015
  1296 00000817 80FB07                  	cmp	bl, 7 ; check for IRQ 8 to IRQ 15 
  1297                                  	;jna	iiret
  1298                                  	; 02/01/2022
  1299 0000081A 7604                    	jna	short iiz
  1300                                  iiy:
  1301 0000081C B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1302 0000081E E6A0                    	out	0A0h, al ; the 2nd 8259
  1303                                  iiz:
  1304 00000820 E983010000              	jmp     iiret
  1305                                  	;
  1306                                  	; 22/08/2014
  1307                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1308                                  	;out	20h, al	; 8259 PORT
  1309                                  	;
  1310                                  	;pop	es
  1311                                  	;pop	ds
  1312                                  	;pop	edi
  1313                                  	;pop	esi
  1314                                  	;pop	ebx
  1315                                  	;pop 	eax
  1316                                  	;iret
  1317                                  
  1318                                  	; 02/04/2015
  1319                                  	; 25/08/2014
  1320                                  exc0:
  1321 00000825 6A00                            push 	dword 0
  1322 00000827 E990000000                      jmp     cpu_except
  1323                                  exc1:
  1324 0000082C 6A01                            push 	dword 1
  1325 0000082E E989000000                      jmp     cpu_except
  1326                                  exc2:
  1327 00000833 6A02                            push 	dword 2
  1328 00000835 E982000000                      jmp     cpu_except
  1329                                  exc3:
  1330 0000083A 6A03                            push 	dword 3
  1331 0000083C EB7E                            jmp     cpu_except
  1332                                  exc4:
  1333 0000083E 6A04                            push 	dword 4
  1334 00000840 EB7A                            jmp     cpu_except
  1335                                  exc5:
  1336 00000842 6A05                            push 	dword 5
  1337 00000844 EB76                            jmp     cpu_except
  1338                                  exc6:
  1339 00000846 6A06                            push 	dword 6
  1340 00000848 EB72                            jmp     cpu_except
  1341                                  exc7:
  1342 0000084A 6A07                            push 	dword 7
  1343 0000084C EB6E                            jmp     cpu_except
  1344                                  exc8:
  1345                                  	; [esp] = Error code
  1346 0000084E 6A08                            push 	dword 8
  1347 00000850 EB5C                            jmp     cpu_except_en
  1348                                  exc9:
  1349 00000852 6A09                            push 	dword 9
  1350 00000854 EB66                            jmp     cpu_except
  1351                                  exc10:
  1352                                  	; [esp] = Error code
  1353 00000856 6A0A                            push 	dword 10
  1354 00000858 EB54                            jmp     cpu_except_en
  1355                                  exc11:
  1356                                  	; [esp] = Error code
  1357 0000085A 6A0B                            push 	dword 11
  1358 0000085C EB50                            jmp     cpu_except_en
  1359                                  exc12:
  1360                                  	; [esp] = Error code
  1361 0000085E 6A0C                            push 	dword 12
  1362 00000860 EB4C                            jmp     cpu_except_en
  1363                                  exc13:
  1364                                  	; [esp] = Error code
  1365 00000862 6A0D                            push 	dword 13
  1366 00000864 EB48                            jmp     cpu_except_en
  1367                                  exc14:
  1368                                  	; [esp] = Error code
  1369 00000866 6A0E                            push 	dword 14
  1370 00000868 EB44                    	jmp	short cpu_except_en
  1371                                  exc15:
  1372 0000086A 6A0F                            push 	dword 15
  1373 0000086C EB4E                            jmp     cpu_except
  1374                                  exc16:
  1375 0000086E 6A10                            push 	dword 16
  1376 00000870 EB4A                            jmp     cpu_except
  1377                                  exc17:
  1378                                  	; [esp] = Error code
  1379 00000872 6A11                            push 	dword 17
  1380 00000874 EB38                    	jmp	short cpu_except_en
  1381                                  exc18:
  1382 00000876 6A12                            push 	dword 18
  1383 00000878 EB42                    	jmp	short cpu_except
  1384                                  exc19:
  1385 0000087A 6A13                            push 	dword 19
  1386 0000087C EB3E                    	jmp	short cpu_except
  1387                                  exc20:
  1388 0000087E 6A14                            push 	dword 20
  1389 00000880 EB3A                    	jmp	short cpu_except
  1390                                  exc21:
  1391 00000882 6A15                            push 	dword 21
  1392 00000884 EB36                    	jmp	short cpu_except
  1393                                  exc22:
  1394 00000886 6A16                            push 	dword 22
  1395 00000888 EB32                    	jmp	short cpu_except
  1396                                  exc23:
  1397 0000088A 6A17                            push 	dword 23
  1398 0000088C EB2E                    	jmp	short cpu_except
  1399                                  exc24:
  1400 0000088E 6A18                            push 	dword 24
  1401 00000890 EB2A                    	jmp	short cpu_except
  1402                                  exc25:
  1403 00000892 6A19                            push 	dword 25
  1404 00000894 EB26                    	jmp	short cpu_except
  1405                                  exc26:
  1406 00000896 6A1A                            push 	dword 26
  1407 00000898 EB22                    	jmp	short cpu_except
  1408                                  exc27:
  1409 0000089A 6A1B                            push 	dword 27
  1410 0000089C EB1E                    	jmp	short cpu_except
  1411                                  exc28:
  1412 0000089E 6A1C                            push 	dword 28
  1413 000008A0 EB1A                    	jmp	short cpu_except
  1414                                  exc29:
  1415 000008A2 6A1D                            push 	dword 29
  1416 000008A4 EB16                    	jmp	short cpu_except
  1417                                  exc30:
  1418 000008A6 6A1E                            push 	dword 30
  1419 000008A8 EB04                    	jmp	short cpu_except_en
  1420                                  exc31:
  1421 000008AA 6A1F                            push 	dword 31
  1422 000008AC EB0E                            jmp     short cpu_except
  1423                                  
  1424                                  	; 02/01/2022
  1425                                  	; 19/10/2015
  1426                                  	; 19/09/2015
  1427                                  	; 01/09/2015
  1428                                  	; 28/08/2015
  1429                                  	; 28/08/2014
  1430                                  cpu_except_en:
  1431 000008AE 87442404                	xchg	eax, [esp+4] ; Error code
  1432 000008B2 36A3[886B0000]          	mov	[ss:error_code], eax
  1433 000008B8 58                      	pop	eax  ; Exception number
  1434 000008B9 870424                  	xchg	eax, [esp]
  1435                                  		; eax = eax before exception
  1436                                  		; [esp] -> exception number
  1437                                  		; [esp+4] -> EIP to return
  1438                                  	; 19/10/2015
  1439                                  	; 19/09/2015
  1440                                  	; 01/09/2015
  1441                                  	; 28/08/2015
  1442                                  	; 29/08/2014
  1443                                  	; 28/08/2014
  1444                                  	; 25/08/2014
  1445                                  	; 21/08/2014
  1446                                  cpu_except:	; CPU Exceptions
  1447 000008BC FC                      	cld
  1448 000008BD 870424                  	xchg	eax, [esp] 
  1449                                  		; eax = Exception number
  1450                                  		; [esp] = eax (before exception)
  1451 000008C0 53                      	push	ebx
  1452 000008C1 56                      	push	esi
  1453 000008C2 57                      	push	edi
  1454 000008C3 1E                      	push 	ds
  1455 000008C4 06                      	push 	es
  1456                                  	; 28/08/2015
  1457 000008C5 66BB1000                	mov	bx, KDATA
  1458 000008C9 8EDB                    	mov	ds, bx
  1459 000008CB 8EC3                    	mov	es, bx
  1460 000008CD 0F20DB                  	mov	ebx, cr3
  1461 000008D0 53                      	push	ebx ; (*) page directory
  1462                                  	; 19/10/2015
  1463 000008D1 FC                      	cld
  1464                                  	; 25/03/2015
  1465 000008D2 8B1D[D86A0000]          	mov	ebx, [k_page_dir]
  1466 000008D8 0F22DB                  	mov	cr3, ebx
  1467                                  	; 28/08/2015
  1468 000008DB 83F80E                  	cmp	eax, 0Eh ; 14, PAGE FAULT
  1469 000008DE 7513                    	jne	short cpu_except_nfp
  1470 000008E0 E884270000              	call	page_fault_handler
  1471 000008E5 21C0                    	and 	eax, eax
  1472                                  	;jz	iiretp ; 01/09/2015
  1473                                  	; 02/01/2022
  1474 000008E7 7505                    	jnz	short cpu_except_pf
  1475 000008E9 E9B6000000              	jmp	iiretp
  1476                                  cpu_except_pf:
  1477 000008EE B80E000000              	mov	eax, 0Eh ; 14
  1478                                  cpu_except_nfp:
  1479                                  	; 02/04/2015
  1480 000008F3 BB[1C060000]            	mov	ebx, hang
  1481 000008F8 875C241C                	xchg	ebx, [esp+28]
  1482                                  		; EIP (points to instruction which faults)
  1483                                  	  	; New EIP (hang)
  1484 000008FC 891D[8C6B0000]          	mov	[FaultOffset], ebx
  1485 00000902 C744242008000000        	mov	dword [esp+32], KCODE ; kernel's code segment
  1486 0000090A 814C242400020000        	or	dword [esp+36], 200h ; enable interrupts (set IF)
  1487                                  	;
  1488 00000912 88C4                    	mov	ah, al
  1489 00000914 240F                    	and	al, 0Fh
  1490 00000916 3C09                    	cmp	al, 9
  1491 00000918 7602                    	jna	short h1ok
  1492 0000091A 0407                    	add	al, 'A'-':'
  1493                                  h1ok:
  1494 0000091C D0EC                    	shr	ah, 1
  1495 0000091E D0EC                    	shr	ah, 1
  1496 00000920 D0EC                    	shr	ah, 1
  1497 00000922 D0EC                    	shr	ah, 1
  1498 00000924 80FC09                  	cmp	ah, 9
  1499 00000927 7603                    	jna	short h2ok
  1500 00000929 80C407                  	add	ah, 'A'-':'
  1501                                  h2ok:	
  1502 0000092C 86E0                    	xchg 	ah, al	
  1503 0000092E 66053030                	add	ax, '00'
  1504 00000932 66A3[B6660000]          	mov	[excnstr], ax
  1505                                  	;
  1506                                  	; 29/08/2014
  1507 00000938 A1[8C6B0000]            	mov	eax, [FaultOffset]
  1508 0000093D 51                      	push	ecx
  1509 0000093E 52                      	push	edx
  1510 0000093F 89E3                    	mov	ebx, esp
  1511                                  	; 28/08/2015
  1512 00000941 B910000000              	mov	ecx, 16	  ; divisor value to convert binary number
  1513                                  			  ; to hexadecimal string
  1514                                  	;mov	ecx, 10	    ; divisor to convert
  1515                                  			    ; binary number to decimal string
  1516                                  b2d1:
  1517 00000946 31D2                    	xor	edx, edx
  1518 00000948 F7F1                    	div	ecx
  1519                                  	;push	dx
  1520                                  	; 02/01/2022
  1521 0000094A 52                      	push	edx
  1522 0000094B 39C8                    	cmp	eax, ecx
  1523 0000094D 73F7                    	jnb	short b2d1
  1524 0000094F BF[C1660000]            	mov	edi, EIPstr ; EIP value
  1525                                  			    ; points to instruction which faults
  1526                                  	; 28/08/2015
  1527 00000954 89C2                    	mov	edx, eax
  1528                                  b2d2:
  1529                                  	;add	al, '0'
  1530 00000956 8A82[06170000]          	mov	al, [edx+hexchrs]
  1531 0000095C AA                      	stosb		    ; write hexadecimal digit to its place
  1532 0000095D 39E3                    	cmp	ebx, esp
  1533 0000095F 7605                    	jna	short b2d3
  1534                                  	; 02/01/2022
  1535 00000961 58                      	pop	eax
  1536                                  	;pop	ax
  1537 00000962 88C2                    	mov	dl, al
  1538 00000964 EBF0                    	jmp	short b2d2
  1539                                  b2d3:
  1540 00000966 B068                    	mov 	al, 'h' ; 28/08/2015
  1541 00000968 AA                      	stosb
  1542 00000969 B020                    	mov	al, 20h	    ; space
  1543 0000096B AA                      	stosb
  1544 0000096C 30C0                    	xor	al, al	    ; to do it an ASCIIZ string	
  1545 0000096E AA                      	stosb
  1546                                  	;
  1547 0000096F 5A                      	pop	edx
  1548 00000970 59                      	pop	ecx
  1549                                  	;
  1550 00000971 B44F                    	mov	ah, 4Fh	; red (4) background, 
  1551                                  			; white (F) forecolor
  1552 00000973 BE[A6660000]            	mov	esi, exc_msg ; message offset
  1553                                  	;
  1554 00000978 EB11                    	jmp	short piemsg
  1555                                  	;
  1556                                          ;add    dword [scr_row], 0A0h
  1557                                          ;mov    edi, [scr_row]
  1558                                          ;
  1559                                  	;call 	printk
  1560                                  	;
  1561                                  	;mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1562                                  	;out	20h, al	; 8259 PORT
  1563                                  	;
  1564                                  	;pop	es
  1565                                  	;pop	ds
  1566                                  	;pop	edi
  1567                                  	;pop	esi
  1568                                  	;pop 	eax
  1569                                  	;iret
  1570                                  	
  1571                                  	; 28/08/2015
  1572                                  	; 23/02/2015
  1573                                  	; 20/08/2014
  1574                                  ignore_int:
  1575 0000097A 50                      	push	eax
  1576 0000097B 53                      	push	ebx ; 23/02/2015
  1577 0000097C 56                      	push	esi
  1578 0000097D 57                      	push	edi
  1579 0000097E 1E                      	push 	ds
  1580 0000097F 06                      	push 	es
  1581                                  	; 28/08/2015
  1582 00000980 0F20D8                  	mov	eax, cr3
  1583 00000983 50                      	push	eax ; (*) page directory
  1584                                  	;
  1585 00000984 B467                    	mov	ah, 67h	; brown (6) background, 
  1586                                  			; light gray (7) forecolor
  1587 00000986 BE[64660000]            	mov	esi, int_msg ; message offset
  1588                                  piemsg:
  1589                                          ; 27/08/2014
  1590 0000098B 8105[28660000]A000-             add     dword [scr_row], 0A0h
  1590 00000993 0000               
  1591 00000995 8B3D[28660000]                  mov     edi, [scr_row]
  1592                                          ;
  1593 0000099B E8B6FCFFFF              	call 	printk
  1594                                  	;
  1595                                  	; 23/02/2015
  1596 000009A0 B020                    	mov	al, 20h  ; END OF INTERRUPT COMMAND TO
  1597 000009A2 E6A0                    	out	0A0h, al ; the 2nd 8259
  1598                                  iiretp: ; 01/09/2015
  1599                                  	; 28/08/2015
  1600 000009A4 58                      	pop	eax ; (*) page directory
  1601 000009A5 0F22D8                  	mov	cr3, eax
  1602                                  	;
  1603                                  iiret:
  1604                                  	; 22/08/2014
  1605 000009A8 B020                    	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  1606 000009AA E620                    	out	20h, al	; 8259 PORT
  1607                                  	;
  1608 000009AC 07                      	pop	es
  1609 000009AD 1F                      	pop	ds
  1610 000009AE 5F                      	pop	edi
  1611 000009AF 5E                      	pop	esi
  1612 000009B0 5B                      	pop	ebx ; 29/08/2014
  1613 000009B1 58                      	pop 	eax
  1614 000009B2 CF                      	iretd
  1615                                  
  1616                                  	; 26/02/2022
  1617                                  	; 26/02/2015
  1618                                  	; 07/09/2014
  1619                                  	; 25/08/2014
  1620                                  rtc_int:       ; Real Time Clock Interrupt (IRQ 8)
  1621                                  	; 22/08/2014
  1622 000009B3 50                      	push	eax
  1623 000009B4 53                      	push	ebx ; 29/08/2014
  1624 000009B5 56                      	push	esi
  1625 000009B6 57                      	push	edi
  1626 000009B7 1E                      	push 	ds
  1627 000009B8 06                      	push 	es
  1628                                  	;
  1629 000009B9 B810000000              	mov	eax, KDATA
  1630 000009BE 8ED8                    	mov	ds, ax
  1631 000009C0 8EC0                    	mov	es, ax
  1632                                  	;
  1633                                  	; 25/08/2014
  1634                                  	;call	rtc_p
  1635                                  	; 26/02/2022
  1636 000009C2 FF15[15070000]          	call	[x_rtci]
  1637                                  	;
  1638                                  	; 22/02/2015 - dsectpm.s
  1639                                  	; [ source: http://wiki.osdev.org/RTC ]
  1640                                  	; read status register C to complete procedure
  1641                                  	;(it is needed to get a next IRQ 8) 
  1642 000009C8 B00C                    	mov	al, 0Ch ; 
  1643 000009CA E670                    	out	70h, al ; select register C
  1644 000009CC 90                      	nop
  1645 000009CD E471                    	in	al, 71h ; just throw away contents
  1646                                  	; 22/02/2015
  1647 000009CF B020                    	MOV	AL,EOI		; END OF INTERRUPT
  1648 000009D1 E6A0                    	OUT	INTB00,AL	; FOR CONTROLLER #2
  1649                                  	;
  1650 000009D3 EBD3                    	jmp	short iiret	
  1651                                  
  1652                                  	; 22/08/2014
  1653                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios.asm)
  1654                                  	; (INT 1Ah)
  1655                                  	;; Linux (v0.12) source code (main.c) by Linus Torvalds (1991)
  1656                                  time_of_day:
  1657 000009D5 E866010000              	call	UPD_IPR		; WAIT TILL UPDATE NOT IN PROGRESS
  1658 000009DA 726F                            jc      short rtc_retn 
  1659 000009DC B000                    	mov	al, CMOS_SECONDS
  1660 000009DE E847010000              	call	CMOS_READ
  1661 000009E3 A2[4C6B0000]            	mov	[time_seconds], al 
  1662 000009E8 B002                    	mov	al, CMOS_MINUTES
  1663 000009EA E83B010000              	call	CMOS_READ
  1664 000009EF A2[4D6B0000]            	mov	[time_minutes], al 
  1665 000009F4 B004                    	mov	al, CMOS_HOURS
  1666 000009F6 E82F010000              	call	CMOS_READ
  1667 000009FB A2[4E6B0000]                    mov     [time_hours], al
  1668 00000A00 B006                    	mov	al, CMOS_DAY_WEEK 
  1669 00000A02 E823010000              	call	CMOS_READ
  1670 00000A07 A2[4F6B0000]            	mov	[date_wday], al
  1671 00000A0C B007                     	mov	al, CMOS_DAY_MONTH
  1672 00000A0E E817010000              	call	CMOS_READ
  1673 00000A13 A2[506B0000]            	mov	[date_day], al
  1674 00000A18 B008                    	mov	al, CMOS_MONTH
  1675 00000A1A E80B010000              	call	CMOS_READ
  1676 00000A1F A2[516B0000]            	mov	[date_month], al
  1677 00000A24 B009                    	mov	al, CMOS_YEAR
  1678 00000A26 E8FF000000              	call	CMOS_READ
  1679 00000A2B A2[526B0000]            	mov	[date_year], al
  1680 00000A30 B032                    	mov	al, CMOS_CENTURY
  1681 00000A32 E8F3000000              	call	CMOS_READ
  1682 00000A37 A2[536B0000]            	mov	[date_century], al
  1683                                  	;
  1684 00000A3C B000                    	mov	al, CMOS_SECONDS
  1685 00000A3E E8E7000000              	call 	CMOS_READ
  1686 00000A43 3A05[4C6B0000]          	cmp	al, [time_seconds]
  1687 00000A49 758A                    	jne	short time_of_day
  1688                                  
  1689                                  rtc_retn:
  1690 00000A4B C3                      	retn
  1691                                  
  1692                                  rtci_default:
  1693                                  	; 26/02/2022 (Temporary!)
  1694                                  	; (default real time clock handler in multitasking mode)
  1695                                  	; ((2 rtc ticks per second after 'setup_rtc_int'))
  1696 00000A4C FF05[946B0000]          	inc	dword [rtc_ticks] ; real time clock counter
  1697                                  			; (not used in anywhere of kernel for now!)
  1698 00000A52 C3                      	retn
  1699                                  
  1700                                  rtc_p:	
  1701                                  	; 07/09/2014
  1702                                  	; 29/08/2014
  1703                                  	; 27/08/2014
  1704                                  	; 25/08/2014
  1705                                   	; Print Real Time Clock content
  1706                                  	;
  1707                                  	;
  1708 00000A53 E87DFFFFFF              	call	time_of_day
  1709 00000A58 72F1                    	jc	short rtc_retn
  1710                                  	;
  1711 00000A5A 3A05[18670000]          	cmp	al, [ptime_seconds]
  1712 00000A60 74E9                            je      short rtc_retn ; 29/08/2014
  1713                                  	;
  1714 00000A62 A2[18670000]            	mov	[ptime_seconds], al
  1715                                  	;
  1716 00000A67 A0[536B0000]            	mov	al, [date_century]
  1717 00000A6C E8EA000000              	call	bcd_to_ascii
  1718 00000A71 66A3[E5660000]          	mov	[datestr+6], ax
  1719 00000A77 A0[526B0000]            	mov	al, [date_year]
  1720 00000A7C E8DA000000              	call	bcd_to_ascii
  1721 00000A81 66A3[E7660000]          	mov	[datestr+8], ax
  1722 00000A87 A0[516B0000]            	mov	al, [date_month]
  1723 00000A8C E8CA000000              	call	bcd_to_ascii
  1724 00000A91 66A3[E2660000]          	mov	[datestr+3], ax
  1725 00000A97 A0[506B0000]            	mov	al, [date_day]
  1726 00000A9C E8BA000000              	call	bcd_to_ascii
  1727 00000AA1 66A3[DF660000]          	mov	[datestr], ax
  1728                                  	;
  1729 00000AA7 0FB61D[4F6B0000]        	movzx	ebx, byte [date_wday]
  1730 00000AAE C0E302                  	shl 	bl, 2
  1731 00000AB1 81C3[F8660000]          	add	ebx, daytmp
  1732 00000AB7 8B03                    	mov	eax, [ebx]
  1733 00000AB9 A3[EA660000]            	mov	[daystr], eax
  1734                                  	;
  1735 00000ABE A0[4E6B0000]            	mov	al, [time_hours]
  1736 00000AC3 E893000000              	call	bcd_to_ascii
  1737 00000AC8 66A3[EE660000]          	mov	[timestr], ax
  1738 00000ACE A0[4D6B0000]            	mov	al, [time_minutes]
  1739 00000AD3 E883000000              	call	bcd_to_ascii
  1740 00000AD8 66A3[F1660000]          	mov	[timestr+3], ax
  1741 00000ADE A0[4C6B0000]            	mov	al, [time_seconds]
  1742 00000AE3 E873000000              	call	bcd_to_ascii
  1743 00000AE8 66A3[F4660000]          	mov	[timestr+6], ax
  1744                                  	;		
  1745 00000AEE BE[CD660000]            	mov	esi, rtc_msg ; message offset
  1746                                  	; 23/02/2015
  1747 00000AF3 52                      	push	edx
  1748 00000AF4 51                      	push	ecx
  1749                                  	; 07/09/2014
  1750                                  	;mov	bx, 2	; Video page 2
  1751                                  	; 02/01/2022
  1752 00000AF5 29DB                    	sub	ebx, ebx
  1753 00000AF7 B307                    	mov	bl, 7	; Video page 7 
  1754                                  prtmsg:
  1755 00000AF9 AC                      	lodsb
  1756 00000AFA 08C0                    	or	al, al
  1757 00000AFC 740D                    	jz	short prtmsg_ok
  1758 00000AFE 56                      	push	esi
  1759                                  	; 02/01/2022
  1760 00000AFF 53                      	push	ebx
  1761                                  	;push	bx
  1762 00000B00 B43F                            mov	ah, 3Fh	; cyan (6) background, 
  1763                                  			; white (F) forecolor
  1764 00000B02 E8BF080000              	call 	write_tty
  1765                                  	;pop	bx
  1766                                  	; 02/01/2022
  1767 00000B07 5B                      	pop	ebx
  1768 00000B08 5E                      	pop	esi
  1769 00000B09 EBEE                    	jmp	short prtmsg
  1770                                  	;
  1771                                  	;mov	edi, 0B8000h+0A0h+0A0h ; Row 2
  1772                                  	;call	printk
  1773                                  prtmsg_ok:
  1774                                  	; 07/09/2014
  1775                                  	;xor	dx, dx		; column 0, row 0
  1776                                  	; 02/01/2022
  1777 00000B0B 31D2                    	xor	edx, edx
  1778 00000B0D E8BE090000              	call	set_cpos	; set curspor position to 0,0 
  1779                                  	; 23/02/2015
  1780 00000B12 59                      	pop	ecx
  1781 00000B13 5A                      	pop	edx
  1782 00000B14 C3                      	retn
  1783                                  
  1784                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  1785                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  1786                                  default_irq7:
  1787                                  	; 24/12/2021
  1788                                  	;push	ax
  1789 00000B15 50                      	push	eax
  1790 00000B16 B00B                    	mov	al, 0Bh  ; In-Service register
  1791 00000B18 E620                    	out	20h, al
  1792 00000B1A EB00                            jmp short $+2
  1793 00000B1C EB00                    	jmp short $+2
  1794 00000B1E E420                    	in	al, 20h
  1795 00000B20 2480                    	and 	al, 80h ; bit 7 (is it real IRQ 7 or fake?)
  1796 00000B22 7404                            jz      short irq7_iret ; Fake (spurious) IRQ, do not send EOI 
  1797 00000B24 B020                            mov     al, 20h ; EOI
  1798 00000B26 E620                    	out	20h, al 
  1799                                  irq7_iret:
  1800                                  	;pop	ax
  1801                                  	; 24/12/2021
  1802 00000B28 58                      	pop	eax
  1803 00000B29 CF                      	iretd	
  1804                                  	
  1805                                  	; 24/12/2021
  1806                                  	; 22/08/2014
  1807                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (test4.asm)
  1808                                  CMOS_READ:
  1809 00000B2A 9C                      	pushf		; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  1810 00000B2B D0C0                    	rol	al, 1	; MOVE NMI BIT TO LOW POSITION
  1811 00000B2D F9                      	stc		; FORCE NMI BIT ON IN CARRY FLAG
  1812 00000B2E D0D8                    	rcr	al, 1	; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  1813 00000B30 FA                      	cli		; DISABLE INTERRUPTS
  1814 00000B31 E670                    	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  1815 00000B33 90                      	nop		; I/O DELAY
  1816 00000B34 E471                    	in	al, CMOS_DATA	; READ THE REQUESTED CMOS LOCATION
  1817                                  	;push	ax	; SAVE (AH) REGISTER VALUE AND CMOS BYTE
  1818                                  	; 24/12/2021
  1819 00000B36 50                      	push	eax
  1820                                  	; 15/03/2015 ; IBM PC/XT Model 286 BIOS source code 
  1821                                  		     ; ----- 10/06/85 (test4.asm)
  1822 00000B37 B01E                    	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  1823                                  	;mov	al, CMOS_REG_D*2 ; GET ADDRESS OF DEFAULT LOCATION
  1824 00000B39 D0D8                    	rcr	al, 1	; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  1825 00000B3B E670                    	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  1826                                  	;pop	ax	; RESTORE (AH) AND (AL), CMOS BYTE
  1827                                  	; 24/12/2021
  1828 00000B3D 58                      	pop	eax
  1829 00000B3E 9D                      	popf	
  1830 00000B3F C3                      	retn		; RETURN WITH FLAGS RESTORED
  1831                                  
  1832                                  	; 22/08/2014
  1833                                  	; IBM PC/AT BIOS source code ----- 10/06/85 (bios2.asm)
  1834                                  UPD_IPR:				; WAIT TILL UPDATE NOT IN PROGRESS
  1835 00000B40 51                      	push	ecx
  1836 00000B41 B9FFFF0000              	mov	ecx, 65535		; SET TIMEOUT LOOP COUNT (= 800)
  1837                                  		; mov cx, 800	
  1838                                  UPD_10:
  1839 00000B46 B00A                    	mov	al, CMOS_REG_A		; ADDRESS STATUS REGISTER A
  1840 00000B48 FA                      	cli				; NO TIMER INTERRUPTS DURING UPDATES
  1841 00000B49 E8DCFFFFFF              	call	CMOS_READ		; READ UPDATE IN PROCESS FLAG
  1842 00000B4E A880                    	test	al, 80h			; IF UIP BIT IS ON ( CANNOT READ TIME )
  1843 00000B50 7406                    	jz	short UPD_90		; EXIT WITH CY= 0 IF CAN READ CLOCK NOW
  1844 00000B52 FB                      	sti				; ALLOW INTERRUPTS WHILE WAITING
  1845 00000B53 E2F1                    	loop	UPD_10			; LOOP TILL READY OR TIMEOUT
  1846 00000B55 31C0                    	xor	eax, eax		; CLEAR RESULTS IF ERROR
  1847                                  		; xor ax, ax
  1848 00000B57 F9                      	stc				; SET CARRY FOR ERROR
  1849                                  UPD_90:
  1850 00000B58 59                      	pop	ecx			; RESTORE CALLERS REGISTER
  1851 00000B59 FA                      	cli				; INTERRUPTS OFF DURING SET
  1852 00000B5A C3                      	retn				; RETURN WITH CY FLAG SET
  1853                                  
  1854                                  bcd_to_ascii:
  1855                                  	; 25/08/2014
  1856                                  	; INPUT ->
  1857                                  	;	al = Packed BCD number
  1858                                  	; OUTPUT ->
  1859                                  	;	ax  = ASCII word/number
  1860                                  	;
  1861                                  	; Erdogan Tan - 1998 (proc_hex) - TRDOS.ASM (2004-2011)
  1862                                  	;
  1863 00000B5B D410                    	db 0D4h,10h                     ; Undocumented inst. AAM
  1864                                  					; AH = AL / 10h
  1865                                  					; AL = AL MOD 10h
  1866 00000B5D 660D3030                	or ax,'00'                      ; Make it ASCII based
  1867                                  
  1868 00000B61 86E0                            xchg ah, al 
  1869                                  	
  1870 00000B63 C3                      	retn	
  1871                                  	
  1872                                  
  1873                                  %include 'keyboard.inc' ; 07/03/2015
  1874                              <1> ; Retro UNIX 386 v1 Kernel - KEYBOARD.INC
  1875                              <1> ; Last Modification: 23/02/2022
  1876                              <1> ;		    (Keyboard Data is in 'KYBDATA.INC')	
  1877                              <1> ;
  1878                              <1> ; ///////// KEYBOARD FUNCTIONS (PROCEDURES) ///////////////
  1879                              <1> 
  1880                              <1> ; 04/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  1881                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  1882                              <1> ; 30/06/2015
  1883                              <1> ; 11/03/2015
  1884                              <1> ; 28/02/2015
  1885                              <1> ; 25/02/2015
  1886                              <1> ; 20/02/2015
  1887                              <1> ; 18/02/2015
  1888                              <1> ; 03/12/2014
  1889                              <1> ; 07/09/2014
  1890                              <1> ; KEYBOARD INTERRUPT HANDLER
  1891                              <1> ; (kb_int - Retro UNIX 8086 v1 - U0.ASM, 30/06/2014)
  1892                              <1> 
  1893                              <1> ;getch:
  1894                              <1> ;	; 18/02/2015
  1895                              <1> ;	; This routine will be replaced with Retro UNIX 386
  1896                              <1> ;	; version of Retro UNIX 8086 getch (tty input)
  1897                              <1> ;	; routine, later... (multi tasking ability)
  1898                              <1> ;	; 28/02/2015
  1899                              <1> ;	sti	; enable interrupts
  1900                              <1> ;	;
  1901                              <1> ;	;push	esi
  1902                              <1> ;	;push	ebx
  1903                              <1> ;	;xor	ebx, ebx
  1904                              <1> ;	;mov	bl, [ptty]  ; active_page
  1905                              <1> ;	;mov	esi, ebx
  1906                              <1> ;	;shl 	si, 1
  1907                              <1> ;	;add	esi, ttychr
  1908                              <1> ;getch_1:
  1909                              <1> ;	;mov	ax, [esi]
  1910                              <1> ;	mov	ax, [ttychr] ; video page 0 (tty0)
  1911                              <1> ;	and	ax, ax
  1912                              <1> ;	jz	short getch_2
  1913                              <1> ;	mov	word [ttychr], 0
  1914                              <1> ;	;mov	word [esi], 0
  1915                              <1> ;	;pop	ebx
  1916                              <1> ;	;pop	esi
  1917                              <1> ;	retn
  1918                              <1> ;getch_2:
  1919                              <1> ;	hlt	; not proper for multi tasking!
  1920                              <1> ;		; (temporary halt for now)
  1921                              <1> ;		; 'sleep' on tty 
  1922                              <1> ;		; will (must) be located here		
  1923                              <1> ;	nop
  1924                              <1> ;	jmp	short getch_1
  1925                              <1> 
  1926                              <1> keyb_int:
  1927                              <1> 	; 23/02/2022
  1928                              <1> 	; 30/06/2015
  1929                              <1> 	; 25/02/2015
  1930                              <1> 	; 20/02/2015
  1931                              <1> 	; 03/12/2014 (getc_int - INT 16h modifications)
  1932                              <1> 	; 07/09/2014 - Retro UNIX 386 v1
  1933                              <1> 	; 30/06/2014
  1934                              <1> 	; 10/05/2013	
  1935                              <1>       	; Retro Unix 8086 v1 feature only!
  1936                              <1> 	; 03/03/2014
  1937                              <1> 	
  1938 00000B64 1E                  <1> 	push	ds
  1939 00000B65 53                  <1> 	push	ebx
  1940 00000B66 50                  <1> 	push	eax
  1941                              <1> 	;
  1942                              <1> 	; 23/02/2022
  1943 00000B67 9C                  <1> 	pushfd
  1944 00000B68 0E                  <1> 	push	cs
  1945                              <1> 	;mov	ax, KDATA
  1946 00000B69 31C0                <1> 	xor	eax, eax
  1947 00000B6B B010                <1> 	mov	al, KDATA
  1948 00000B6D 8ED8                <1> 	mov	ds, ax
  1949                              <1> 	;
  1950                              <1> 	;pushfd
  1951                              <1> 	;push	cs
  1952 00000B6F E810020000          <1> 	call	kb_int   ; int_09h
  1953                              <1> 	;
  1954 00000B74 B411                <1> 	mov	ah, 11h	 ; 03/12/2014	
  1955                              <1> 	;call	getc
  1956 00000B76 E854000000          <1> 	call	int_16h  ; 30/06/2015
  1957 00000B7B 744E                <1> 	jz	short keyb_int4
  1958                              <1> 	;
  1959 00000B7D B410                <1> 	mov	ah, 10h	 ; 03/12/2014
  1960                              <1> 	;call	getc
  1961 00000B7F E84B000000          <1> 	call	int_16h  ; 30/06/2015
  1962                              <1> 	;
  1963                              <1> 	; 20/02/2015
  1964 00000B84 0FB61D[066B0000]    <1>         movzx   ebx, byte [ptty]  ; active_page
  1965                              <1> 	;
  1966 00000B8B 20C0                <1> 	and 	al, al
  1967 00000B8D 751D                <1> 	jnz	short keyb_int1
  1968                              <1> 	;
  1969 00000B8F 80FC68              <1> 	cmp	ah, 68h	 ; ALT + F1 key
  1970 00000B92 7218                <1> 	jb	short keyb_int1
  1971 00000B94 80FC6F              <1> 	cmp	ah, 6Fh  ; ALT + F8 key	
  1972 00000B97 7713                <1> 	ja	short keyb_int1
  1973                              <1> 	;
  1974 00000B99 88D8                <1> 	mov	al, bl
  1975 00000B9B 0468                <1> 	add	al, 68h
  1976 00000B9D 38E0                <1> 	cmp	al, ah
  1977 00000B9F 7409                <1> 	je	short keyb_int0
  1978 00000BA1 88E0                <1> 	mov	al, ah
  1979 00000BA3 2C68                <1> 	sub	al, 68h
  1980 00000BA5 E83F0A0000          <1> 	call	tty_sw
  1981                              <1> 	;movzx	ebx, [ptty]  ; active_page
  1982                              <1> keyb_int0: ; 30/06/2015
  1983                              <1> 	;xor	ax, ax
  1984                              <1> 	; 23/02/2022
  1985 00000BAA 31C0                <1> 	xor	eax, eax
  1986                              <1> keyb_int1:
  1987 00000BAC D0E3                <1> 	shl	bl, 1
  1988 00000BAE 81C3[086B0000]      <1> 	add	ebx, ttychr
  1989                              <1> 	;
  1990                              <1> 	;23/02/2022
  1991 00000BB4 09C0                <1> 	or	eax, eax
  1992                              <1> 	;or	ax, ax
  1993 00000BB6 7406                <1> 	jz	short keyb_int2
  1994                              <1> 	;
  1995 00000BB8 66833B00            <1> 	cmp 	word [ebx], 0
  1996 00000BBC 7703                <1>         ja      short keyb_int3 
  1997                              <1> keyb_int2:
  1998 00000BBE 668903              <1>         mov	[ebx], ax  ; Save ascii code
  1999                              <1> 			   ; and scan code of the character
  2000                              <1> 			   ; for current tty (or last tty
  2001                              <1> 			   ; just before tty switch).
  2002                              <1> keyb_int3:
  2003 00000BC1 A0[066B0000]        <1>         mov     al, [ptty]
  2004 00000BC6 E8C0430000          <1> 	call	wakeup
  2005                              <1> 	;
  2006                              <1> keyb_int4:
  2007 00000BCB 58                  <1> 	pop	eax
  2008 00000BCC 5B                  <1> 	pop	ebx
  2009 00000BCD 1F                  <1> 	pop	ds
  2010 00000BCE CF                  <1> 	iret
  2011                              <1> 
  2012                              <1> ; 18/02/2015
  2013                              <1> ; REMINDER: Only 'keyb_int' (IRQ 9) must call getc.
  2014                              <1> ; 'keyb_int' always handles 'getc' at 1st and puts the
  2015                              <1> ; scancode and ascii code of the character 
  2016                              <1> ; in the tty input (ttychr) buffer. 
  2017                              <1> ; Test procedures must call 'getch' for tty input
  2018                              <1> ; otherwise, 'getc' will not be able to return to the caller
  2019                              <1> ; due to infinite (key press) waiting loop.
  2020                              <1> ; 
  2021                              <1> ; 03/12/2014
  2022                              <1> ; 26/08/2014
  2023                              <1> ; KEYBOARD I/O
  2024                              <1> ; (INT_16h - Retro UNIX 8086 v1 - U9.ASM, 30/06/2014)
  2025                              <1> 
  2026                              <1> ;NOTE: 'k0' to 'k7' are name of OPMASK registers.
  2027                              <1> ;	(The reason of using '_k' labels!!!) (27/08/2014)    
  2028                              <1> ;NOTE: 'NOT' keyword is '~' unary operator in NASM.
  2029                              <1> ;	('NOT LC_HC' --> '~LC_HC') (bit reversing operator)
  2030                              <1> 
  2031                              <1> int_16h: ; 30/06/2015
  2032                              <1> ;getc:
  2033 00000BCF 9C                  <1> 	pushfd	; 28/08/2014
  2034 00000BD0 0E                  <1> 	push 	cs
  2035 00000BD1 E826000000          <1> 	call 	getc_int
  2036 00000BD6 C3                  <1> 	retn
  2037                              <1> 
  2038                              <1> ; 24/12/2021
  2039                              <1> 
  2040                              <1> 	;-----	SHIFT STATUS
  2041                              <1> _K3E:                                   ; GET THE EXTENDED SHIFT STATUS FLAGS
  2042 00000BD7 8A25[04650000]      <1> 	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2043 00000BDD 80E404              <1> 	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2044                              <1> 	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2045                              <1> 	;shl	ah, cl			; BIT 7 POSITION
  2046 00000BE0 C0E405              <1>         shl	ah, 5
  2047 00000BE3 A0[04650000]        <1> 	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2048 00000BE8 2473                <1> 	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2049 00000BEA 08C4                <1> 	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2050 00000BEC A0[06650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2051 00000BF1 240C                <1> 	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2052 00000BF3 08C4                <1> 	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2053                              <1> _K3:
  2054 00000BF5 A0[03650000]        <1> 	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2055 00000BFA EB2B                <1> 	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2056                              <1> 
  2057                              <1> getc_int:
  2058                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2059                              <1> 	; 28/02/2015
  2060                              <1> 	; 03/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2061                              <1> 	;	      instead of pc-at bios - 1985-)
  2062                              <1> 	; 28/08/2014 (_k1d)
  2063                              <1> 	; 30/06/2014
  2064                              <1> 	; 03/03/2014
  2065                              <1> 	; 28/02/2014
  2066                              <1> 	; Derived from "KEYBOARD_IO_1" procedure of IBM "pc-xt-286" 
  2067                              <1> 	; rombios source code (21/04/1986)
  2068                              <1> 	;	 'keybd.asm', INT 16H, KEYBOARD_IO
  2069                              <1> 	;
  2070                              <1> 	; KYBD --- 03/06/86  KEYBOARD BIOS
  2071                              <1> 	;
  2072                              <1> 	;--- INT 16 H -----------------------------------------------------------------
  2073                              <1> 	; KEYBOARD I/O								      :
  2074                              <1> 	;	THESE ROUTINES PROVIDE READ KEYBOARD SUPPORT			      :
  2075                              <1> 	; INPUT									      :
  2076                              <1> 	;	(AH)= 00H  READ THE NEXT ASCII CHARACTER ENTERED FROM THE KEYBOARD,   :
  2077                              <1> 	;		   RETURN THE RESULT IN (AL), SCAN CODE IN (AH).              :
  2078                              <1> 	;		   THIS IS THE COMPATIBLE READ INTERFACE, EQUIVALENT TO THE   :
  2079                              <1> 	;                  STANDARD PC OR PCAT KEYBOARD				      :	
  2080                              <1> 	;-----------------------------------------------------------------------------:
  2081                              <1> 	;	(AH)= 01H  SET THE ZERO FLAG TO INDICATE IF AN ASCII CHARACTER IS     :
  2082                              <1> 	;		   AVAILABLE TO BE READ FROM THE KEYBOARD BUFFER.	      :
  2083                              <1> 	;		   (ZF)= 1 -- NO CODE AVAILABLE			              :
  2084                              <1> 	;		   (ZF)= 0 -- CODE IS AVAILABLE  (AX)= CHARACTER              :
  2085                              <1> 	;		   IF (ZF)= 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS :
  2086                              <1> 	;		   IN (AX), AND THE ENTRY REMAINS IN THE BUFFER.              :
  2087                              <1> 	;		   THIS WILL RETURN ONLY PC/PCAT KEYBOARD COMPATIBLE CODES    :
  2088                              <1> 	;-----------------------------------------------------------------------------:	
  2089                              <1> 	;	(AH)= 02H  RETURN THE CURRENT SHIFT STATUS IN AL REGISTER             :
  2090                              <1> 	;		   THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE        :
  2091                              <1> 	;		   EQUATES FOR @KB_FLAG		                              :
  2092                              <1> 	;-----------------------------------------------------------------------------:	
  2093                              <1> 	;	(AH)= 03H  SET TYPAMATIC RATE AND DELAY                               :
  2094                              <1> 	;	      (AL) = 05H                                                      :
  2095                              <1> 	;	      (BL) = TYPAMATIC RATE (BITS 5 - 7 MUST BE RESET TO 0)           :
  2096                              <1> 	;		       							      :
  2097                              <1> 	;                     REGISTER     RATE      REGISTER     RATE                :
  2098                              <1> 	;                      VALUE     SELECTED     VALUE     SELECTED              :
  2099                              <1> 	;                     --------------------------------------------            :
  2100                              <1> 	;			00H        30.0        10H        7.5                 :
  2101                              <1> 	;			01H        26.7        11H        6.7                 :
  2102                              <1> 	;			02H        24.0        12H        6.0                 :
  2103                              <1> 	;			03H        21.8        13H        5.5                 :
  2104                              <1> 	;			04H        20.0        14H        5.0                 :
  2105                              <1> 	;			05H        18.5        15H        4.6                 :
  2106                              <1> 	;			06H        17.1        16H        4.3                 :
  2107                              <1> 	;			07H        16.0        17H        4.0                 :
  2108                              <1> 	;			08H        15.0        18H        3.7                 :
  2109                              <1> 	;			09H        13.3        19H        3.3                 :
  2110                              <1> 	;			0AH        12.0        1AH        3.0                 :
  2111                              <1> 	;			0BH        10.9        1BH        2.7                 :
  2112                              <1>         ;			0CH        10.0        1CH        2.5                 :
  2113                              <1> 	;			0DH         9.2        1DH        2.3                 :
  2114                              <1> 	;			0EH         8.6        1EH        2.1                 :
  2115                              <1> 	;			0FH         8.0        1FH        2.0                 :
  2116                              <1> 	;									      :
  2117                              <1> 	;	      (BH) = TYPAMATIC DELAY  (BITS 2 - 7 MUST BE RESET TO 0)         :
  2118                              <1> 	;		       							      :
  2119                              <1> 	;                     REGISTER     DELAY                                      :
  2120                              <1> 	;                      VALUE       VALUE                                      :
  2121                              <1> 	;                     ------------------                                      :
  2122                              <1> 	;			00H        250 ms                                     :
  2123                              <1> 	;			01H        500 ms                                     :
  2124                              <1> 	;			02H        750 ms                                     :
  2125                              <1> 	;			03H       1000 ms                                     :
  2126                              <1> 	;-----------------------------------------------------------------------------:
  2127                              <1> 	;	(AH)= 05H  PLACE ASCII CHARACTER/SCAN CODE COMBINATION IN KEYBOARD    :
  2128                              <1> 	;		   BUFFER AS IF STRUCK FROM KEYBOARD                          :
  2129                              <1> 	;		   ENTRY:  (CL) = ASCII CHARACTER		              :
  2130                              <1> 	;		           (CH) = SCAN CODE                                   :
  2131                              <1> 	;		   EXIT:   (AH) = 00H = SUCCESSFUL OPERATION                  :
  2132                              <1> 	;		           (AL) = 01H = UNSUCCESSFUL - BUFFER FULL            :
  2133                              <1> 	;		   FLAGS:  CARRY IF ERROR                                     :
  2134                              <1> 	;-----------------------------------------------------------------------------:		
  2135                              <1> 	;	(AH)= 10H  EXTENDED READ INTERFACE FOR THE ENHANCED KEYBOARD,         :
  2136                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=0                            :
  2137                              <1> 	;-----------------------------------------------------------------------------:
  2138                              <1> 	;	(AH)= 11H  EXTENDED ASCII STATUS FOR THE ENHANCED KEYBOARD,           :
  2139                              <1> 	;		   OTHERWISE SAME AS FUNCTION AH=1                            :
  2140                              <1> 	;-----------------------------------------------------------------------------:	
  2141                              <1> 	;	(AH)= 12H  RETURN THE EXTENDED SHIFT STATUS IN AX REGISTER            :
  2142                              <1> 	;		   AL = BITS FROM KB_FLAG, AH = BITS FOR LEFT AND RIGHT       :
  2143                              <1> 	;		   CTL AND ALT KEYS FROM KB_FLAG_1 AND KB_FLAG_3              :
  2144                              <1> 	; OUTPUT					                              :
  2145                              <1> 	;	AS NOTED ABOVE, ONLY (AX) AND FLAGS CHANGED	                      :
  2146                              <1> 	;	ALL REGISTERS RETAINED		                                      :
  2147                              <1> 	;------------------------------------------------------------------------------
  2148                              <1> 	
  2149 00000BFC FB                  <1> 	sti				; INTERRUPTS BACK ON
  2150 00000BFD 1E                  <1> 	push	ds			; SAVE CURRENT DS
  2151 00000BFE 53                  <1> 	push	ebx			; SAVE BX TEMPORARILY
  2152                              <1> 	;push	ecx			; SAVE CX TEMPORARILY
  2153 00000BFF 66BB1000            <1>         mov     bx, KDATA 
  2154 00000C03 8EDB                <1> 	mov	ds, bx			; PUT SEGMENT VALUE OF DATA AREA INTO DS
  2155 00000C05 08E4                <1> 	or	ah, ah			; CHECK FOR (AH)= 00H
  2156 00000C07 742D                <1> 	jz	short _K1		; ASCII_READ
  2157 00000C09 FECC                <1> 	dec	ah                      ; CHECK FOR (AH)= 01H
  2158 00000C0B 7446                <1>         jz      short _K2               ; ASCII_STATUS
  2159 00000C0D FECC                <1> 	dec	ah			; CHECK FOR (AH)= 02H
  2160 00000C0F 74E4                <1>         jz      short _K3               ; SHIFT STATUS
  2161 00000C11 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 03H	
  2162 00000C13 745B                <1>         jz      short _K300             ; SET TYPAMATIC RATE/DELAY
  2163 00000C15 80EC02              <1> 	sub	ah, 2			; CHECK FOR (AH)= 05H	
  2164 00000C18 7479                <1>         jz      short _K500             ; KEYBOARD WRITE         
  2165                              <1> _KIO1:	
  2166 00000C1A 80EC0B              <1> 	sub	ah, 11			; AH =  10H
  2167 00000C1D 740B                <1> 	jz	short _K1E		; EXTENDED ASCII READ
  2168 00000C1F FECC                <1> 	dec	ah			; CHECK FOR (AH)= 11H
  2169 00000C21 7421                <1> 	jz	short _K2E		; EXTENDED_ASCII_STATUS
  2170 00000C23 FECC                <1> 	dec	ah			; CHECK FOR (AH)= 12H
  2171 00000C25 74B0                <1> 	jz	short _K3E		; EXTENDED_SHIFT_STATUS
  2172                              <1> _KIO_EXIT:
  2173                              <1> 	;pop	ecx			; RECOVER REGISTER
  2174 00000C27 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2175 00000C28 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2176 00000C29 CF                  <1> 	iretd				; INVALID COMMAND, EXIT
  2177                              <1> 
  2178                              <1> 	;-----	ASCII CHARACTER
  2179                              <1> _K1E:	
  2180 00000C2A E891000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER (EXTENDED)
  2181 00000C2F E804010000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2182 00000C34 EBF1                <1> 	jmp	short _KIO_EXIT         ; GIVE IT TO THE CALLER
  2183                              <1> _K1:	
  2184 00000C36 E885000000          <1> 	call	_K1S			; GET A CHARACTER FROM THE BUFFER
  2185 00000C3B E803010000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2186 00000C40 72F4                <1> 	jc	short _K1		; CARRY SET MEANS TROW CODE AWAY
  2187                              <1> _K1A:
  2188 00000C42 EBE3                <1> 	jmp	short _KIO_EXIT         ; RETURN TO CALLER
  2189                              <1> 
  2190                              <1> 	;-----	ASCII STATUS
  2191                              <1> _K2E:	
  2192 00000C44 E8C2000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER (EXTENDED)
  2193 00000C49 7420                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2194 00000C4B 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2195 00000C4C E8E7000000          <1> 	call	_KIO_E_XLAT		; ROUTINE TO XLATE FOR EXTENDED CALLS
  2196 00000C51 EB17                <1> 	jmp	short _K2A	        ; GIVE IT TO THE CALLER
  2197                              <1> _K2:	
  2198 00000C53 E8B3000000          <1> 	call	_K2S			; TEST FOR CHARACTER IN BUFFER
  2199 00000C58 7411                <1> 	jz	short _K2B		; RETURN IF BUFFER EMPTY
  2200 00000C5A 9C                  <1> 	pushf				; SAVE ZF FROM TEST
  2201 00000C5B E8E3000000          <1> 	call	_KIO_S_XLAT		; ROUTINE TO XLATE FOR STANDARD CALLS
  2202 00000C60 7308                <1> 	jnc	short _K2A	        ; CARRY CLEAR MEANS PASS VALID CODE
  2203 00000C62 9D                  <1> 	popf				; INVALID CODE FOR THIS TYPE OF CALL
  2204 00000C63 E858000000          <1> 	call	_K1S			; THROW THE CHARACTER AWAY
  2205 00000C68 EBE9                <1> 	jmp	short _K2		; GO LOOK FOR NEXT CHAR, IF ANY
  2206                              <1> _K2A:
  2207 00000C6A 9D                  <1> 	popf				; RESTORE ZF FROM TEST
  2208                              <1> _K2B:
  2209                              <1> 	;pop	ecx			; RECOVER REGISTER
  2210 00000C6B 5B                  <1> 	pop	ebx			; RECOVER REGISTER
  2211 00000C6C 1F                  <1> 	pop	ds			; RECOVER SEGMENT
  2212 00000C6D CA0400              <1> 	retf	4			; THROW AWAY (e)FLAGS
  2213                              <1> 
  2214                              <1> ; 24/12/2021
  2215                              <1> ;	;-----	SHIFT STATUS
  2216                              <1> ;_K3E:                                  ; GET THE EXTENDED SHIFT STATUS FLAGS
  2217                              <1> ;	mov	ah, [KB_FLAG_1]		; GET SYSTEM SHIFT KEY STATUS
  2218                              <1> ;	and	ah, SYS_SHIFT		; MASK ALL BUT SYS KEY BIT
  2219                              <1> ;	;mov	cl, 5			; SHIFT THEW SYSTEMKEY BIT OVER TO
  2220                              <1> ;	;shl	ah, cl			; BIT 7 POSITION
  2221                              <1> ;       shl	ah, 5
  2222                              <1> ;	mov	al, [KB_FLAG_1]		; GET SYSTEM SHIFT STATES BACK
  2223                              <1> ;	and	al, 01110011b		; ELIMINATE SYS SHIFT, HOLD_STATE AND INS_SHIFT
  2224                              <1> ;	or	ah, al                  ; MERGE REMAINING BITS INTO AH
  2225                              <1> ;	mov	al, [KB_FLAG_3]		; GET RIGHT CTL AND ALT
  2226                              <1> ;	and	al, 00001100b		; ELIMINATE LC_E0 AND LC_E1
  2227                              <1> ;	or	ah, al			; OR THE SHIFT FLAGS TOGETHER
  2228                              <1> ;_K3:
  2229                              <1> ;	mov	al, [KB_FLAG]		; GET THE SHIFT STATUS FLAGS
  2230                              <1> ;	jmp	short _KIO_EXIT		; RETURN TO CALLER
  2231                              <1> 
  2232                              <1> 	;-----	SET TYPAMATIC RATE AND DELAY
  2233                              <1> _K300:
  2234 00000C70 3C05                <1> 	cmp	al, 5			; CORRECT FUNCTION CALL?
  2235 00000C72 75B3                <1> 	jne	short _KIO_EXIT		; NO, RETURN
  2236 00000C74 F6C3E0              <1>      	test	bl, 0E0h		; TEST FOR OUT-OF-RANGE RATE
  2237 00000C77 75AE                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2238 00000C79 F6C7FC              <1> 	test	BH, 0FCh		; TEST FOR OUT-OF-RANGE DELAY
  2239 00000C7C 75A9                <1> 	jnz	short _KIO_EXIT		; RETURN IF SO
  2240 00000C7E B0F3                <1> 	mov	al, KB_TYPA_RD		; COMMAND FOR TYPAMATIC RATE/DELAY		
  2241 00000C80 E880060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2242                              <1> 	;mov	cx, 5			; SHIFT COUNT
  2243                              <1> 	;shl	bh, cl			; SHIFT DELAY OVER
  2244 00000C85 C0E705              <1> 	shl	bh, 5
  2245 00000C88 88D8                <1> 	mov	al, bl			; PUT IN RATE
  2246 00000C8A 08F8                <1> 	or	al, bh			; AND DELAY
  2247 00000C8C E874060000          <1> 	call	SND_DATA		; SEND TO KEYBOARD	
  2248 00000C91 EB94                <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER
  2249                              <1> 
  2250                              <1> 	;-----	WRITE TO KEYBOARD BUFFER
  2251                              <1> _K500:
  2252 00000C93 56                  <1> 	push	esi			; SAVE SI (esi)
  2253 00000C94 FA                  <1> 	cli				; 
  2254 00000C95 8B1D[14650000]      <1>      	mov	ebx, [BUFFER_TAIL]	; GET THE 'IN TO' POINTER TO THE BUFFER
  2255 00000C9B 89DE                <1> 	mov	esi, ebx		; SAVE A COPY IN CASE BUFFER NOT FULL
  2256 00000C9D E8D1000000          <1> 	call	_K4			; BUMP THE POINTER TO SEE IF BUFFER IS FULL
  2257 00000CA2 3B1D[10650000]      <1> 	cmp	ebx, [BUFFER_HEAD]	; WILL THE BUFFER OVERRUN IF WE STORE THIS?
  2258 00000CA8 740D                <1> 	je	short _K502		; YES - INFORM CALLER OF ERROR		
  2259 00000CAA 66890E              <1> 	mov	[esi], cx		; NO - PUT ASCII/SCAN CODE INTO BUFFER	
  2260 00000CAD 891D[14650000]      <1> 	mov	[BUFFER_TAIL], ebx	; ADJUST 'IN TO' POINTER TO REFLECT CHANGE
  2261 00000CB3 28C0                <1> 	sub	al, al			; TELL CALLER THAT OPERATION WAS SUCCESSFUL
  2262 00000CB5 EB02                <1> 	jmp	short _K504		; SUB INSTRUCTION ALSO RESETS CARRY FLAG
  2263                              <1> _K502:
  2264 00000CB7 B001                <1> 	mov	al, 01h			; BUFFER FULL INDICATION
  2265                              <1> _K504:
  2266 00000CB9 FB                  <1> 	sti				
  2267 00000CBA 5E                  <1> 	pop	esi			; RECOVER SI (esi)
  2268 00000CBB E967FFFFFF          <1>         jmp     _KIO_EXIT               ; RETURN TO CALLER WITH STATUS IN AL
  2269                              <1> 
  2270                              <1> 	;-----	READ THE KEY TO FIGURE OUT WHAT TO DO -----
  2271                              <1> _K1S:
  2272 00000CC0 FA                  <1> 	cli	; 03/12/2014
  2273 00000CC1 8B1D[10650000]      <1>         mov     ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2274 00000CC7 3B1D[14650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2275                              <1> 	;jne	short _K1U		; IF ANYTHING IN BUFFER SKIP INTERRUPT
  2276 00000CCD 750F                <1> 	jne	short _k1x ; 03/12/2014
  2277                              <1> 	;
  2278                              <1> 	; 03/12/2014
  2279                              <1> 	; 28/08/2014
  2280                              <1> 	; PERFORM OTHER FUNCTION ?? here !
  2281                              <1> 	;; MOV	AX, 9002h		; MOVE IN WAIT CODE & TYPE
  2282                              <1> 	;; INT 	15H			; PERFORM OTHER FUNCTION
  2283                              <1> _K1T:                                   ; ASCII READ
  2284 00000CCF FB                  <1> 	sti				; INTERRUPTS BACK ON DURING LOOP
  2285 00000CD0 90                  <1> 	nop				; ALLOW AN INTERRUPT TO OCCUR
  2286                              <1> _K1U:	
  2287 00000CD1 FA                  <1> 	cli				; INTERRUPTS BACK OFF
  2288 00000CD2 8B1D[10650000]      <1>         mov    	ebx, [BUFFER_HEAD] 	; GET POINTER TO HEAD OF BUFFER
  2289 00000CD8 3B1D[14650000]      <1>         cmp     ebx, [BUFFER_TAIL] 	; TEST END OF BUFFER
  2290                              <1> _k1x:
  2291 00000CDE 53                  <1> 	push	ebx			; SAVE ADDRESS		
  2292 00000CDF 9C                  <1> 	pushf				; SAVE FLAGS
  2293 00000CE0 E8D4060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2294 00000CE5 8A1D[05650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2295 00000CEB 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2296 00000CED 80E307              <1> 	and	bl, 07h	; KB_LEDS	; ISOLATE INDICATOR BITS
  2297 00000CF0 7406                <1> 	jz	short _K1V		; IF NO CHANGE BYPASS UPDATE
  2298 00000CF2 E86E060000          <1> 	call	SND_LED1
  2299 00000CF7 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2300                              <1> _K1V:
  2301 00000CF8 9D                  <1> 	popf				; RESTORE FLAGS
  2302 00000CF9 5B                  <1> 	pop	ebx			; RESTORE ADDRESS
  2303 00000CFA 74D3                <1>         je      short _K1T              ; LOOP UNTIL SOMETHING IN BUFFER
  2304                              <1> 	;
  2305 00000CFC 668B03              <1> 	mov	ax, [ebx] 		; GET SCAN CODE AND ASCII CODE
  2306 00000CFF E86F000000          <1>         call    _K4                     ; MOVE POINTER TO NEXT POSITION
  2307 00000D04 891D[10650000]      <1>         mov     [BUFFER_HEAD], ebx      ; STORE VALUE IN VARIABLE
  2308 00000D0A C3                  <1> 	retn				; RETURN
  2309                              <1> 
  2310                              <1> 	;-----	READ THE KEY TO SEE IF ONE IS PRESENT -----
  2311                              <1> _K2S:
  2312 00000D0B FA                  <1> 	cli				; INTERRUPTS OFF
  2313 00000D0C 8B1D[10650000]      <1>         mov     ebx, [BUFFER_HEAD]      ; GET HEAD POINTER
  2314 00000D12 3B1D[14650000]      <1>         cmp     ebx, [BUFFER_TAIL]      ; IF EQUAL (Z=1) THEN NOTHING THERE
  2315 00000D18 668B03              <1> 	mov	ax, [ebx]
  2316 00000D1B 9C                  <1> 	pushf				; SAVE FLAGS
  2317                              <1> 	;push	ax			; SAVE CODE
  2318                              <1> 	; 24/12/2021
  2319 00000D1C 50                  <1> 	push	eax
  2320 00000D1D E897060000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2321 00000D22 8A1D[05650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2322 00000D28 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2323 00000D2A 80E307              <1> 	and	bl, 07h ; KB_LEDS	; ISOLATE INDICATOR BITS
  2324 00000D2D 7405                <1> 	jz	short _K2T		; IF NO CHANGE BYPASS UPDATE
  2325 00000D2F E81A060000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2326                              <1> _K2T:
  2327                              <1> 	;pop	ax			; RESTORE CODE
  2328                              <1> 	; 24/12/2021
  2329 00000D34 58                  <1> 	pop	eax
  2330 00000D35 9D                  <1> 	popf				; RESTORE FLAGS
  2331 00000D36 FB                  <1> 	sti				; INTERRUPTS BACK ON
  2332 00000D37 C3                  <1> 	retn				; RETURN
  2333                              <1> 
  2334                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR EXTENDED CALLS -----
  2335                              <1> _KIO_E_XLAT:
  2336 00000D38 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2337 00000D3A 7506                <1> 	jne	short _KIO_E_RET	; NO, PASS IT ON
  2338 00000D3C 08E4                <1>         or 	ah, ah			; AH = 0 IS SPECIAL CASE
  2339 00000D3E 7402                <1>         jz	short _KIO_E_RET        ; PASS THIS ON UNCHANGED
  2340 00000D40 30C0                <1> 	xor	al, al			; OTHERWISE SET AL = 0
  2341                              <1> _KIO_E_RET:				
  2342 00000D42 C3                  <1> 	retn				; GO BACK
  2343                              <1> 
  2344                              <1> 	;-----	ROUTINE TO TRANSLATE SCAN CODE PAIRS FOR STANDARD CALLS -----
  2345                              <1> _KIO_S_XLAT:
  2346 00000D43 80FCE0              <1> 	cmp	ah, 0E0h		; IS IT KEYPAD ENTER OR / ?
  2347 00000D46 750F                <1> 	jne	short _KIO_S2		; NO, CONTINUE
  2348 00000D48 3C0D                <1> 	cmp	al, 0Dh			; KEYPAD ENTER CODE?
  2349 00000D4A 7408                <1>         je	short _KIO_S1		; YES, MASSAGE A BIT
  2350 00000D4C 3C0A                <1> 	cmp	al, 0Ah			; CTRL KEYPAD ENTER CODE?
  2351 00000D4E 7404                <1>         je	short _KIO_S1		; YES, MASSAGE THE SAME
  2352 00000D50 B435                <1> 	mov	ah, 35h			; NO, MUST BE KEYPAD /
  2353                              <1> _kio_ret: ; 03/12/2014
  2354 00000D52 F8                  <1> 	clc
  2355 00000D53 C3                  <1> 	retn
  2356                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2357                              <1> _KIO_S1:				
  2358 00000D54 B41C                <1> 	mov	ah, 1Ch			; CONVERT TO COMPATIBLE OUTPUT
  2359                              <1> 	;jmp	short _KIO_USE		; GIVE TO CALLER
  2360 00000D56 C3                  <1> 	retn
  2361                              <1> _KIO_S2:		
  2362 00000D57 80FC84              <1> 	cmp	ah, 84h			; IS IT ONE OF EXTENDED ONES?
  2363 00000D5A 7715                <1> 	ja	short _KIO_DIS		; YES, THROW AWAY AND GET ANOTHER CHAR
  2364 00000D5C 3CF0                <1> 	cmp	al, 0F0h		; IS IT ONE OF THE FILL-INs?
  2365 00000D5E 7506                <1>         jne	short _KIO_S3		; NO, TRY LAST TEST
  2366 00000D60 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2367 00000D62 740C                <1>         jz	short _KIO_USE		; PASS THIS ON UNCHANGED
  2368 00000D64 EB0B                <1> 	jmp	short _KIO_DIS		; THROW AWAY THE REST
  2369                              <1> _KIO_S3:
  2370 00000D66 3CE0                <1> 	cmp	al, 0E0h		; IS IT AN EXTENSION OF A PREVIOUS ONE?
  2371                              <1> 	;jne	short _KIO_USE		; NO, MUST BE A STANDARD CODE
  2372 00000D68 75E8                <1> 	jne	short _kio_ret
  2373 00000D6A 08E4                <1> 	or	ah, ah			; AH = 0 IS SPECIAL CASE
  2374 00000D6C 7402                <1>         jz	short _KIO_USE		; JUMP IF AH = 0
  2375 00000D6E 30C0                <1> 	xor	al, al			; CONVERT TO COMPATIBLE OUTPUT
  2376                              <1> 	;jmp	short _KIO_USE		; PASS IT ON TO CALLER
  2377                              <1> _KIO_USE:
  2378                              <1> 	;clc				; CLEAR CARRY TO INDICATE GOOD CODE
  2379 00000D70 C3                  <1> 	retn				; RETURN	
  2380                              <1> _KIO_DIS:
  2381 00000D71 F9                  <1> 	stc				; SET CARRY TO INDICATE DISCARD CODE
  2382 00000D72 C3                  <1> 	retn				; RETURN
  2383                              <1> 
  2384                              <1> 	;-----	INCREMENT BUFFER POINTER ROUTINE -----
  2385                              <1> _K4:    
  2386 00000D73 43                  <1> 	inc     ebx
  2387 00000D74 43                  <1> 	inc	ebx			; MOVE TO NEXT WORD IN LIST
  2388 00000D75 3B1D[0C650000]      <1>         cmp     ebx, [BUFFER_END] 	; AT END OF BUFFER?
  2389                              <1>         ;jne    short _K5               ; NO, CONTINUE
  2390 00000D7B 7206                <1> 	jb	short _K5
  2391 00000D7D 8B1D[08650000]      <1>         mov     ebx, [BUFFER_START]     ; YES, RESET TO BUFFER BEGINNING
  2392                              <1> _K5:
  2393 00000D83 C3                  <1> 	retn
  2394                              <1> 
  2395                              <1> ; 20/02/2015
  2396                              <1> ; 05/12/2014
  2397                              <1> ; 26/08/2014
  2398                              <1> ; KEYBOARD (HARDWARE) INTERRUPT -  IRQ LEVEL 1
  2399                              <1> ; (INT_09h - Retro UNIX 8086 v1 - U9.ASM, 07/03/2014)
  2400                              <1> ;
  2401                              <1> ; Derived from "KB_INT_1" procedure of IBM "pc-at" 
  2402                              <1> ; rombios source code (06/10/1985)
  2403                              <1> ; 'keybd.asm', HARDWARE INT 09h - (IRQ Level 1)
  2404                              <1> 
  2405                              <1> ;--------- 8042 COMMANDS -------------------------------------------------------
  2406                              <1> ENA_KBD		equ	0AEh	; ENABLE KEYBOARD COMMAND
  2407                              <1> DIS_KBD		equ	0ADh	; DISABLE KEYBOARD COMMAND
  2408                              <1> SHUT_CMD	equ	0FEh	; CAUSE A SHUTDOWN COMMAND
  2409                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2410                              <1> STATUS_PORT	equ	064h	; 8042 STATUS PORT
  2411                              <1> INPT_BUF_FULL	equ	00000010b ; 1 = +INPUT BUFFER FULL
  2412                              <1> PORT_A		equ	060h	; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2413                              <1> ;---------- 8042 KEYBOARD RESPONSE ---------------------------------------------
  2414                              <1> KB_ACK		equ	0FAh	; ACKNOWLEDGE PROM TRANSMISSION
  2415                              <1> KB_RESEND	equ	0FEh	; RESEND REQUEST
  2416                              <1> KB_OVER_RUN	equ	0FFh	; OVER RUN SCAN CODE
  2417                              <1> ;---------- KEYBOARD/LED COMMANDS ----------------------------------------------
  2418                              <1> KB_ENABLE	equ	0F4h		; KEYBOARD ENABLE
  2419                              <1> LED_CMD		equ	0EDh		; LED WRITE COMMAND
  2420                              <1> KB_TYPA_RD	equ	0F3h		; TYPAMATIC RATE/DELAY COMMAND
  2421                              <1> ;---------- KEYBOARD SCAN CODES ------------------------------------------------
  2422                              <1> NUM_KEY		equ	69		; SCAN CODE FOR	 NUMBER LOCK KEY
  2423                              <1> SCROLL_KEY	equ	70		; SCAN CODE FOR	 SCROLL LOCK KEY
  2424                              <1> ALT_KEY		equ	56		; SCAN CODE FOR	 ALTERNATE SHIFT KEY
  2425                              <1> CTL_KEY		equ	29		; SCAN CODE FOR	 CONTROL KEY
  2426                              <1> CAPS_KEY	equ	58		; SCAN CODE FOR	 SHIFT LOCK KEY
  2427                              <1> DEL_KEY		equ	83		; SCAN CODE FOR	 DELETE KEY
  2428                              <1> INS_KEY		equ	82		; SCAN CODE FOR	 INSERT KEY
  2429                              <1> LEFT_KEY	equ	42		; SCAN CODE FOR	 LEFT SHIFT
  2430                              <1> RIGHT_KEY	equ	54		; SCAN CODE FOR	 RIGHT SHIFT
  2431                              <1> SYS_KEY		equ	84		; SCAN CODE FOR	 SYSTEM KEY
  2432                              <1> ;---------- ENHANCED KEYBOARD SCAN CODES ---------------------------------------
  2433                              <1> ID_1		equ	0ABh		; 1ST ID CHARACTER FOR KBX
  2434                              <1> ID_2		equ	041h		; 2ND ID CHARACTER FOR KBX
  2435                              <1> ID_2A		equ	054h		; ALTERNATE 2ND ID CHARACTER FOR KBX
  2436                              <1> F11_M		equ	87		; F11 KEY MAKE
  2437                              <1> F12_M		equ	88		; F12 KEY MAKE
  2438                              <1> MC_E0		equ	224		; GENERAL MARKER CODE
  2439                              <1> MC_E1		equ	225		; PAUSE KEY MARKER CODE
  2440                              <1> ;---------- FLAG EQUATES WITHIN @KB_FLAG----------------------------------------
  2441                              <1> RIGHT_SHIFT	equ	00000001b	; RIGHT SHIFT KEY DEPRESSED
  2442                              <1> LEFT_SHIFT	equ	00000010b	; LEFT SHIFT KEY DEPRESSED
  2443                              <1> CTL_SHIFT	equ	00000100b	; CONTROL SHIFT KEY DEPRESSED
  2444                              <1> ALT_SHIFT	equ	00001000b	; ALTERNATE SHIFT KEY DEPRESSED
  2445                              <1> SCROLL_STATE	equ	00010000b	; SCROLL LOCK STATE IS ACTIVE
  2446                              <1> NUM_STATE	equ	00100000b	; NUM LOCK STATE IS ACTIVE
  2447                              <1> CAPS_STATE	equ	01000000b	; CAPS LOCK STATE IS ACTIVE
  2448                              <1> INS_STATE	equ	10000000b	; INSERT STATE IS ACTIVE
  2449                              <1> ;---------- FLAG EQUATES WITHIN	@KB_FLAG_1 -------------------------------------
  2450                              <1> L_CTL_SHIFT	equ	00000001b	; LEFT CTL KEY DOWN
  2451                              <1> L_ALT_SHIFT	equ	00000010b	; LEFT ALT KEY DOWN
  2452                              <1> SYS_SHIFT	equ	00000100b	; SYSTEM KEY DEPRESSED AND HELD
  2453                              <1> HOLD_STATE	equ	00001000b	; SUSPEND KEY HAS BEEN TOGGLED
  2454                              <1> SCROLL_SHIFT	equ	00010000b	; SCROLL LOCK KEY IS DEPRESSED
  2455                              <1> NUM_SHIFT	equ	00100000b	; NUM LOCK KEY IS DEPRESSED
  2456                              <1> CAPS_SHIFT	equ	01000000b	; CAPS LOCK KEY IS DEPRE55ED
  2457                              <1> INS_SHIFT	equ	10000000b	; INSERT KEY IS DEPRESSED
  2458                              <1> ;---------- FLAGS EQUATES WITHIN @KB_FLAG_2 -----------------------------------
  2459                              <1> KB_LEDS		equ	00000111b	; KEYBOARD LED STATE BITS
  2460                              <1> ;		equ	00000001b	; SCROLL LOCK INDICATOR
  2461                              <1> ;		equ	00000010b	; NUM LOCK INDICATOR
  2462                              <1> ;		equ	00000100b	; CAPS LOCK INDICATOR
  2463                              <1> ;		equ	00001000b	; RESERVED (MUST BE ZERO)
  2464                              <1> KB_FA		equ	00010000b	; ACKNOWLEDGMENT RECEIVED
  2465                              <1> KB_FE		equ	00100000b	; RESEND RECEIVED FLAG
  2466                              <1> KB_PR_LED	equ	01000000b	; MODE INDICATOR UPDATE
  2467                              <1> KB_ERR		equ	10000000b	; KEYBOARD TRANSMIT ERROR FLAG
  2468                              <1> ;----------- FLAGS EQUATES WITHIN @KB_FLAG_3 -----------------------------------
  2469                              <1> LC_E1		equ	00000001b	; LAST CODE WAS THE E1 HIDDEN CODE
  2470                              <1> LC_E0		equ	00000010b	; LAST CODE WAS THE E0 HIDDEN CODE
  2471                              <1> R_CTL_SHIFT	equ	00000100b	; RIGHT CTL KEY DOWN
  2472                              <1> R_ALT_SHIFT	equ	00001000b	; RIGHT ALT KEY DOWN
  2473                              <1> GRAPH_ON	equ	00001000b	; ALT GRAPHICS KEY DOWN (WT ONLY)	
  2474                              <1> KBX		equ	00010000b	; ENHANCED KEYBOARD INSTALLED
  2475                              <1> SET_NUM_LK	equ	00100000b	; FORCE NUM LOCK IF READ ID AND KBX
  2476                              <1> LC_AB		equ	01000000b	; LAST CHARACTER WAS FIRST ID CHARACTER
  2477                              <1> RD_ID		equ	10000000b	; DOING A READ ID (MUST BE BIT0)
  2478                              <1> ;
  2479                              <1> ;----------- INTERRUPT EQUATES -------------------------------------------------
  2480                              <1> EOI		equ	020h		; END OF INTERRUPT COMMAND TO 8259
  2481                              <1> INTA00		equ	020h		; 8259 PORT
  2482                              <1> 
  2483                              <1> 
  2484                              <1> kb_int:
  2485                              <1> 
  2486                              <1> ; 24/12/2021 (Retro UNIX 386 v1.1)
  2487                              <1> ; 17/10/2015 ('ctrlbrk') 
  2488                              <1> ; 05/12/2014
  2489                              <1> ; 04/12/2014 (derivation from pc-xt-286 bios source code -1986-, 
  2490                              <1> 	;	      instead of pc-at bios - 1985-)
  2491                              <1> ; 26/08/2014
  2492                              <1> ;
  2493                              <1> ; 03/06/86  KEYBOARD BIOS
  2494                              <1> ;
  2495                              <1> ;--- HARDWARE INT 09H -- (IRQ LEVEL 1) ------------------------------------------
  2496                              <1> ;										;
  2497                              <1> ;	KEYBOARD INTERRUPT ROUTINE						;
  2498                              <1> ;										;
  2499                              <1> ;--------------------------------------------------------------------------------
  2500                              <1> 
  2501                              <1> KB_INT_1:
  2502 00000D84 FB                  <1> 	sti				; ENABLE INTERRUPTS
  2503                              <1> 	;push	ebp
  2504 00000D85 50                  <1> 	push	eax
  2505 00000D86 53                  <1> 	push	ebx
  2506 00000D87 51                  <1> 	push	ecx
  2507 00000D88 52                  <1> 	push	edx
  2508 00000D89 56                  <1> 	push	esi
  2509 00000D8A 57                  <1> 	push	edi
  2510 00000D8B 1E                  <1> 	push	ds
  2511 00000D8C 06                  <1> 	push	es
  2512 00000D8D FC                  <1> 	cld				; FORWARD DIRECTION
  2513 00000D8E 66B81000            <1> 	mov	ax, KDATA
  2514 00000D92 8ED8                <1> 	mov	ds, ax
  2515 00000D94 8EC0                <1> 	mov	es, ax
  2516                              <1> 	;
  2517                              <1> 	;-----	WAIT FOR KEYBOARD DISABLE COMMAND TO BE ACCEPTED
  2518 00000D96 B0AD                <1> 	mov	al, DIS_KBD		; DISABLE THE KEYBOARD COMMAND
  2519 00000D98 E856050000          <1> 	call	SHIP_IT			; EXECUTE DISABLE
  2520 00000D9D FA                  <1> 	cli				; DISABLE INTERRUPTS
  2521 00000D9E B900000100          <1> 	mov	ecx, 10000h		; SET MAXIMUM TIMEOUT
  2522                              <1> KB_INT_01:
  2523 00000DA3 E464                <1> 	in	al, STATUS_PORT		; READ ADAPTER STATUS
  2524 00000DA5 A802                <1> 	test	al, INPT_BUF_FULL	; CHECK INPUT BUFFER FULL STATUS BIT
  2525 00000DA7 E0FA                <1> 	loopnz	KB_INT_01		; WAIT FOR COMMAND TO BE ACCEPTED
  2526                              <1> 	;
  2527                              <1> 	;-----	READ CHARACTER FROM KEYBOARD INTERFACE
  2528 00000DA9 E460                <1> 	in	al, PORT_A		; READ IN THE CHARACTER
  2529                              <1> 	;
  2530                              <1> 	;-----	SYSTEM HOOK INT 15H - FUNCTION 4FH (ON HARDWARE INT LEVEL 9H) 	
  2531                              <1> 	;MOV	AH, 04FH		; SYSTEM INTERCEPT - KEY CODE FUNCTION
  2532                              <1> 	;STC				; SET CY=1 (IN CASE OF IRET)
  2533                              <1> 	;INT	15H			; CASETTE CALL (AL)=KEY SCAN CODE
  2534                              <1> 	;				; RETURNS CY=1 FOR INVALID FUNCTION
  2535                              <1> 	;JC	KB_INT_02		; CONTINUE IF CARRY FLAG SET ((AL)=CODE)
  2536                              <1> 	;JMP	K26			; EXIT IF SYSTEM HANDLES SCAN CODE
  2537                              <1> 	;				; EXT HANDLES HARDWARE EOI AND ENABLE		
  2538                              <1> 	;
  2539                              <1> 	;-----	CHECK FOR A RESEND COMMAND TO KEYBOARD
  2540                              <1> KB_INT_02:				; 	  (AL)= SCAN CODE
  2541 00000DAB FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  2542 00000DAC 3CFE                <1> 	cmp	al, KB_RESEND		; IS THE INPUT A RESEND
  2543 00000DAE 7411                <1>         je      short KB_INT_4          ; GO IF RESEND
  2544                              <1> 	;
  2545                              <1> 	;-----	CHECK FOR RESPONSE TO A COMMAND TO KEYBOARD
  2546 00000DB0 3CFA                <1> 	cmp	al, KB_ACK		; IS THE INPUT AN ACKNOWLEDGE
  2547 00000DB2 751A                <1>         jne     short KB_INT_2          ; GO IF NOT
  2548                              <1> 	;
  2549                              <1> 	;-----	A COMMAND TO THE KEYBOARD WAS ISSUED
  2550 00000DB4 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2551 00000DB5 800D[05650000]10    <1> 	or	byte [KB_FLAG_2], KB_FA ; INDICATE ACK RECEIVED
  2552 00000DBC E963020000          <1>         jmp     K26                     ; RETURN IF NOT (ACK RETURNED FOR DATA)
  2553                              <1> 	;
  2554                              <1> 	;-----	RESEND THE LAST BYTE
  2555                              <1> KB_INT_4:
  2556 00000DC1 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2557 00000DC2 800D[05650000]20    <1> 	or	byte [KB_FLAG_2], KB_FE ; INDICATE RESEND RECEIVED
  2558 00000DC9 E956020000          <1>         jmp     K26                     ; RETURN IF NOT ACK RETURNED FOR DATA)
  2559                              <1> 	;
  2560                              <1> ;-----	UPDATE MODE INDICATORS IF CHANGE IN STATE
  2561                              <1> KB_INT_2:
  2562                              <1> 	;push 	ax			; SAVE DATA IN
  2563                              <1> 	; 24/12/2021
  2564 00000DCE 50                  <1> 	push	eax
  2565 00000DCF E8E5050000          <1> 	call	MAKE_LED		; GO GET MODE INDICATOR DATA BYTE
  2566 00000DD4 8A1D[05650000]      <1> 	mov	bl, [KB_FLAG_2] 	; GET PREVIOUS BITS
  2567 00000DDA 30C3                <1> 	xor	bl, al			; SEE IF ANY DIFFERENT
  2568 00000DDC 80E307              <1> 	and	bl, KB_LEDS		; ISOLATE INDICATOR BITS
  2569 00000DDF 7405                <1> 	jz	short UP0		; IF NO CHANGE BYPASS UPDATE
  2570 00000DE1 E868050000          <1> 	call	SND_LED			; GO TURN ON MODE INDICATORS
  2571                              <1> UP0:
  2572                              <1> 	;pop	ax			; RESTORE DATA IN
  2573                              <1> 	; 24/12/2021
  2574 00000DE6 58                  <1> 	pop	eax
  2575                              <1> ;------------------------------------------------------------------------
  2576                              <1> ;	START OF KEY PROCESSING						;
  2577                              <1> ;------------------------------------------------------------------------
  2578 00000DE7 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE IN AH ALSO
  2579                              <1> 	;
  2580                              <1> 	;-----	TEST FOR OVERRUN SCAN CODE FROM KEYBOARD
  2581 00000DE9 3CFF                <1> 	cmp	al, KB_OVER_RUN		; IS THIS AN OVERRUN CHAR
  2582                              <1>         ;je	K62			; BUFFER_FULL_BEEP
  2583                              <1> 	; 24/12/2021
  2584 00000DEB 7505                <1> 	jne	short K16
  2585 00000DED E9ED040000          <1> 	jmp	K62
  2586                              <1> K16:	
  2587 00000DF2 8A3D[06650000]      <1> 	mov	bh, [KB_FLAG_3]		; LOAD FLAGS FOR TESTING
  2588                              <1> 	;
  2589                              <1> 	;-----	TEST TO SEE IF A READ_ID IS IN PROGRESS
  2590 00000DF8 F6C7C0              <1> 	test 	bh, RD_ID+LC_AB 	; ARE WE DOING A READ ID?
  2591 00000DFB 7442                <1> 	jz	short NOT_ID		; CONTINUE IF NOT
  2592 00000DFD 7914                <1> 	jns	short TST_ID_2		; IS THE RD_ID FLAG ON?
  2593 00000DFF 3CAB                <1> 	cmp	al, ID_1		; IS THIS THE 1ST ID CHARACTER?
  2594 00000E01 7507                <1> 	jne	short RST_RD_ID
  2595 00000E03 800D[06650000]40    <1> 	or	byte [KB_FLAG_3], LC_AB ; INDICATE 1ST ID WAS OK
  2596                              <1> RST_RD_ID:
  2597 00000E0A 8025[06650000]7F    <1> 	and	byte [KB_FLAG_3], ~RD_ID ; RESET THE READ ID FLAG
  2598 00000E11 EB27                <1>         jmp    short ID_EX		; AND EXIT
  2599                              <1> 	; 24/12/2021
  2600                              <1> 	;jmp	K26
  2601                              <1> 	;
  2602                              <1> TST_ID_2:
  2603 00000E13 8025[06650000]BF    <1> 	and	byte [KB_FLAG_3], ~LC_AB ; RESET FLAG
  2604 00000E1A 3C54                <1> 	cmp	al, ID_2A		; IS THIS THE 2ND ID CHARACTER?
  2605 00000E1C 7415                <1>         je	short KX_BIT		; JUMP IF SO
  2606 00000E1E 3C41                <1> 	cmp	al, ID_2		; IS THIS THE 2ND ID CHARACTER?
  2607 00000E20 7518                <1>         jne	short ID_EX		; LEAVE IF NOT
  2608                              <1> 	; 24/12/2021
  2609                              <1> 	;jne	K26
  2610                              <1> 	;
  2611                              <1> 	;-----	A READ ID SAID THAT IT WAS ENHANCED KEYBOARD
  2612 00000E22 F6C720              <1> 	test	bh, SET_NUM_LK 		; SHOULD WE SET NUM LOCK?
  2613 00000E25 740C                <1>         jz      short KX_BIT		; EXIT IF NOT
  2614 00000E27 800D[03650000]20    <1> 	or	byte [KB_FLAG], NUM_STATE ; FORCE NUM LOCK ON
  2615 00000E2E E81B050000          <1> 	call	SND_LED			; GO SET THE NUM LOCK INDICATOR
  2616                              <1> KX_BIT:
  2617 00000E33 800D[06650000]10    <1> 	or	byte [KB_FLAG_3], KBX	; INDICATE ENHANCED KEYBOARD WAS FOUND
  2618 00000E3A E9E5010000          <1> ID_EX:	jmp     K26			; EXIT
  2619                              <1> 	;
  2620                              <1> NOT_ID:
  2621 00000E3F 3CE0                <1> 	cmp	al, MC_E0		; IS THIS THE GENERAL MARKER CODE?
  2622 00000E41 750E                <1> 	jne	short TEST_E1
  2623 00000E43 800D[06650000]12    <1> 	or	byte [KB_FLAG_3], LC_E0+KBX ; SET FLAG BIT, SET KBX, AND
  2624 00000E4A EB10                <1> 	jmp	short EXIT		; THROW AWAY THIS CODE
  2625                              <1> 	; 24/12/2021
  2626 00000E4C E9DA010000          <1> 	jmp	K26A	
  2627                              <1> TEST_E1:	
  2628 00000E51 3CE1                <1> 	cmp	al, MC_E1		; IS THIS THE PAUSE KEY?
  2629 00000E53 750C                <1> 	jne	short NOT_HC
  2630 00000E55 800D[06650000]11    <1> 	or	byte [KB_FLAG_3], LC_E1+KBX ; SET FLAG BIT, SET KBX, AND
  2631 00000E5C E9CA010000          <1> EXIT:	jmp	K26A			; THROW AWAY THIS CODE
  2632                              <1> 	;
  2633                              <1> NOT_HC:
  2634 00000E61 247F                <1> 	and	al, 07Fh		; TURN OFF THE BREAK BIT
  2635 00000E63 F6C702              <1> 	test	bh, LC_E0		; LAST CODE THE E0 MARKER CODE
  2636 00000E66 740D                <1> 	jz	short NOT_LC_E0		; JUMP IF NOT
  2637                              <1> 	;
  2638 00000E68 BF[EE630000]        <1> 	mov	edi, _K6+6		; IS THIS A SHIFT KEY?
  2639 00000E6D AE                  <1> 	scasb
  2640                              <1> 	;je	K26 ; K16B              ; YES, THROW AWAY & RESET FLAG
  2641                              <1> 	; 24/12/2021
  2642 00000E6E 7458                <1> 	je	short K16B
  2643 00000E70 AE                  <1> 	scasb
  2644 00000E71 756A                <1> 	jne	short K16A		; NO, CONTINUE KEY PROCESSING
  2645 00000E73 EB53                <1> 	jmp	short K16B		; YES, THROW AWAY & RESET FLAG
  2646                              <1> 	; 24/12/2021
  2647                              <1> 	;jmp	K26
  2648                              <1> 	;
  2649                              <1> NOT_LC_E0:
  2650 00000E75 F6C701              <1> 	test	bh, LC_E1		; LAST CODE THE E1 MARKER CODE?
  2651 00000E78 7425                <1> 	jz	short T_SYS_KEY		; JUMP IF NOT
  2652 00000E7A B904000000          <1> 	mov	ecx, 4			; LENGHT OF SEARCH
  2653 00000E7F BF[EC630000]        <1> 	mov	edi, _K6+4		; IS THIS AN ALT, CTL, OR SHIFT?
  2654 00000E84 F2AE                <1> 	repne	scasb			; CHECK IT
  2655 00000E86 74D4                <1> 	je	short EXIT		; THROW AWAY IF SO
  2656                              <1> 	; 24/12/2021
  2657                              <1> 	;je	K26A			
  2658                              <1> 	;
  2659 00000E88 3C45                <1> 	cmp	al, NUM_KEY		; IS IT THE PAUSE KEY?
  2660 00000E8A 753C                <1> 	jne	short K16B		; NO, THROW AWAY & RESET FLAG
  2661                              <1> 	; 24/12/2021
  2662                              <1> 	;jne	K26
  2663 00000E8C F6C480              <1> 	test	ah, 80h			; YES, IS IT THE BREAK OF THE KEY?
  2664 00000E8F 7537                <1> 	jnz	short K16B		; YES, THROW THIS AWAY, TOO	
  2665                              <1> 	; 24/12/2021
  2666                              <1> 	;jnz	K26
  2667                              <1>         ; 20/02/2015 
  2668 00000E91 F605[04650000]08    <1> 	test	byte [KB_FLAG_1],HOLD_STATE ; NO, ARE WE PAUSED ALREADY?
  2669 00000E98 752E                <1> 	jnz	short K16B		; YES, THROW AWAY
  2670                              <1> 	; 24/12/2021
  2671                              <1> 	;jnz	K26
  2672 00000E9A E9D6020000          <1> 	jmp     K39P                    ; NO, THIS IS THE REAL PAUSE STATE
  2673                              <1> 	;
  2674                              <1> 	;-----	TEST FOR SYSTEM KEY
  2675                              <1> T_SYS_KEY:
  2676 00000E9F 3C54                <1> 	cmp	al, SYS_KEY		; IS IT THE SYSTEM KEY?
  2677 00000EA1 753A                <1> 	jnz	short K16A		; CONTINUE IF NOT
  2678                              <1> 	;
  2679 00000EA3 F6C480              <1> 	test	ah, 80h			; CHECK IF THIS A BREAK CODE
  2680 00000EA6 7525                <1> 	jnz	short K16C		; DO NOT TOUCH SYSTEM INDICATOR IF TRUE
  2681                              <1> 	;
  2682 00000EA8 F605[04650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; SEE IF IN SYSTEM KEY HELD DOWN 
  2683 00000EAF 7517                <1> 	jnz	short K16B		; IF YES, DO NOT PROCESS SYSTEM INDICATOR	
  2684                              <1> 	;jnz	K26			
  2685                              <1> 	;
  2686 00000EB1 800D[04650000]04    <1> 	or	byte [KB_FLAG_1], SYS_SHIFT ; INDICATE SYSTEM KEY DEPRESSED
  2687 00000EB8 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2688 00000EBA E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2689                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2690 00000EBC B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2691 00000EBE E830040000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2692                              <1> 	; !!! SYSREQ !!! function/system call (INTERRUPT) must be here !!!
  2693                              <1> 	;MOV	AL, 8500H		; FUNCTION VALUE FOR MAKE OF SYSTEM KEY
  2694                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2695                              <1> 	;INT	15H			; USER INTERRUPT	
  2696 00000EC3 E96F010000          <1>         jmp     K27A                    ; END PROCESSING
  2697                              <1> 	;
  2698 00000EC8 E957010000          <1> K16B:	jmp	K26			; IGNORE SYSTEM KEY
  2699                              <1> 	;
  2700                              <1> K16C:
  2701 00000ECD 8025[04650000]FB    <1> 	and	byte [KB_FLAG_1], ~SYS_SHIFT ; TURN OFF SHIFT KEY HELD DOWN
  2702 00000ED4 B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2703 00000ED6 E620                <1> 	out	20h, al ;out INTA00, al ; SEND COMMAND TO INTERRUPT CONTROL PORT
  2704                              <1> 					; INTERRUPT-RETURN-NO-EOI
  2705                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2706                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  2707                              <1> 	;
  2708                              <1> 	;MOV	AX, 8501H		; FUNCTION VALUE FOR BREAK OF SYSTEM KEY
  2709                              <1> 	;STI				; MAKE SURE INTERRUPTS ENABLED
  2710                              <1> 	;INT	15H			; USER INTERRUPT
  2711                              <1> 	;JMP	K27A			; INGONRE SYSTEM KEY				
  2712                              <1> 	;
  2713 00000ED8 E953010000          <1> 	jmp     K27			; IGNORE SYSTEM KEY
  2714                              <1> 	;
  2715                              <1> 	;-----	TEST FOR SHIFT KEYS
  2716                              <1> K16A:
  2717 00000EDD 8A1D[03650000]      <1> 	mov	bl, [KB_FLAG]		; PUT STATE FLAGS IN BL
  2718 00000EE3 BF[E8630000]        <1> 	mov	edi, _K6		; SHIFT KEY TABLE offset
  2719 00000EE8 B908000000          <1> 	mov	ecx, _K6L		; LENGTH
  2720 00000EED F2AE                <1> 	repne	scasb			; LOOK THROUGH THE TABLE FOR A MATCH
  2721 00000EEF 88E0                <1> 	mov	al, ah			; RECOVER SCAN CODE
  2722                              <1>         ;jne    K25                     ; IF NO MATCH, THEN SHIFT NOT FOUND
  2723                              <1> 	; 24/12/2021
  2724 00000EF1 7405                <1> 	je	short K17
  2725 00000EF3 E914010000          <1> 	jmp	K25
  2726                              <1> 	;
  2727                              <1> 	;------	SHIFT KEY FOUND
  2728                              <1> K17:
  2729 00000EF8 81EF[E9630000]      <1>         sub     edi, _K6+1              ; ADJUST PTR TO SCAN CODE MATCH
  2730 00000EFE 8AA7[F0630000]      <1>        	mov     ah, [edi+_K7]       	; GET MASK INTO AH
  2731 00000F04 B102                <1> 	mov	cl, 2			; SETUP COUNT FOR FLAG SHIFTS
  2732 00000F06 A880                <1> 	test	al, 80h			; TEST FOR BREAK KEY
  2733                              <1>         ;jnz	K23                     ; JUMP OF BREAK
  2734                              <1> 	; 24/12/2021
  2735 00000F08 7405                <1> 	jz	short K17C
  2736 00000F0A E999000000          <1> 	jmp	K23
  2737                              <1> 	;
  2738                              <1> 	;-----	SHIFT MAKE FOUND, DETERMINE SET OR TOGGLE
  2739                              <1> K17C:
  2740 00000F0F 80FC10              <1> 	cmp	ah, SCROLL_SHIFT
  2741 00000F12 732C                <1> 	jae	short K18		; IF SCROLL SHIFT OR ABOVE, TOGGLE KEY
  2742                              <1> 	;
  2743                              <1> 	;-----	PLAIN SHIFT KEY, SET SHIFT ON
  2744 00000F14 0825[03650000]      <1> 	or	[KB_FLAG], ah		; TURN ON SHIFT BIT
  2745 00000F1A A80C                <1>         test	al, CTL_SHIFT+ALT_SHIFT ; IS IT ALT OR CTRL?
  2746 00000F1C 7505                <1> 	jnz	short K17D		; YES, MORE FLAGS TO SET
  2747                              <1> 	;jz	K26			; NO, INTERRUPT RETURN
  2748                              <1> 	; 24/12/2021
  2749 00000F1E E901010000          <1> 	jmp	K26
  2750                              <1> K17D:
  2751 00000F23 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF NEW KEYS?
  2752 00000F26 740B                <1> 	jz 	short K17E		; NO, JUMP
  2753 00000F28 0825[06650000]      <1> 	or	[KB_FLAG_3], ah		; SET BITS FOR RIGHT CTRL, ALT
  2754 00000F2E E9F1000000          <1> 	jmp	K26			; INTERRUPT RETURN
  2755                              <1> K17E:
  2756 00000F33 D2EC                <1> 	shr	ah, cl			; MOVE FLAG BITS TWO POSITIONS
  2757 00000F35 0825[04650000]      <1> 	or	[KB_FLAG_1], ah		; SET BITS FOR LEFT CTRL, ALT
  2758 00000F3B E9E4000000          <1> 	jmp	K26
  2759                              <1> 	;
  2760                              <1> 	;-----	TOGGLED SHIFT KEY, TEST FOR 1ST MAKE OR NOT
  2761                              <1> K18:					; SHIFT-TOGGLE
  2762 00000F40 F6C304              <1> 	test	bl, CTL_SHIFT 		; CHECK CTL SHIFT STATE
  2763 00000F43 7405                <1>         jz    	short K18A              ; JUMP IF NOT CTL STATE
  2764                              <1>         ;jnz	K25                     ; JUMP IF CTL STATE
  2765                              <1> 	; 24/12/2021
  2766 00000F45 E9C2000000          <1> 	jmp	K25
  2767                              <1> K18A:
  2768 00000F4A 3C52                <1> 	cmp	al, INS_KEY		; CHECK FOR INSERT KEY
  2769 00000F4C 7525                <1> 	jne	short K22		; JUMP IF NOT INSERT KEY
  2770 00000F4E F6C308              <1> 	test	bl, ALT_SHIFT 		; CHECK FOR ALTERNATE SHIFT
  2771 00000F51 7405                <1>       	jz	short K18B		; JUMP IF NOT ALTERNATE SHIFT	
  2772                              <1> 	;jnz	K25                     ; JUMP IF ALTERNATE SHIFT
  2773                              <1> 	; 24/12/2021
  2774 00000F53 E9B4000000          <1> 	jmp	K25
  2775                              <1> K18B:
  2776 00000F58 F6C702              <1> 	test	bh, LC_E0 ;20/02/2015	; IS THIS NEW INSERT KEY?
  2777 00000F5B 7516                <1> 	jnz	short K22		; YES, THIS ONE'S NEVER A '0'
  2778                              <1> K19:	
  2779 00000F5D F6C320              <1> 	test	bl, NUM_STATE 		; CHECK FOR BASE STATE
  2780 00000F60 750C                <1> 	jnz	short K21		; JUMP IF NUM LOCK IS ON
  2781 00000F62 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST FOR SHIFT STATE
  2782 00000F65 740C                <1> 	jz	short K22		; JUMP IF BASE STATE
  2783                              <1> K20:					; NUMERIC ZERO, NOT INSERT KEY
  2784 00000F67 88C4                <1> 	mov	ah, al			; PUT SCAN CODE BACK IN AH
  2785 00000F69 E99E000000          <1>         jmp	K25               	; NUMERAL '0', STNDRD. PROCESSING
  2786                              <1> K21:					; MIGHT BE NUMERIC
  2787 00000F6E F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT
  2788 00000F71 74F4                <1> 	jz	short K20		; IS NUMERIC, STD. PROC.
  2789                              <1> 	;
  2790                              <1> K22:					; SHIFT TOGGLE KEY HIT; PROCESS IT
  2791 00000F73 8425[04650000]      <1> 	test	ah, [KB_FLAG_1] 	; IS KEY ALREADY DEPRESSED
  2792                              <1> 	;jnz	K26
  2793                              <1> 	; 24/12/2021
  2794 00000F79 7405                <1> 	jz	short K22A
  2795 00000F7B E9A4000000          <1> 	jmp	K26			; JUMP IF KEY ALREADY DEPRESSED
  2796                              <1> K22A:
  2797 00000F80 0825[04650000]      <1>         or      [KB_FLAG_1], ah 	; INDICATE THAT THE KEY IS DEPRESSED
  2798 00000F86 3025[03650000]      <1> 	xor	[KB_FLAG], ah		; TOGGLE THE SHIFT STATE
  2799                              <1> 	;
  2800                              <1> 	;-----	TOGGLE LED IF CAPS, NUM  OR SCROLL KEY DEPRESSED
  2801 00000F8C F6C470              <1> 	test	ah, CAPS_SHIFT+NUM_SHIFT+SCROLL_SHIFT ; SHIFT TOGGLE?
  2802 00000F8F 7407                <1> 	jz	short K22B		; GO IF NOT
  2803                              <1> 	;
  2804                              <1> 	; 24/12/2021
  2805                              <1> 	;push	ax			; SAVE SCAN CODE AND SHIFT MASK
  2806 00000F91 50                  <1> 	push	eax
  2807 00000F92 E8B7030000          <1> 	call	SND_LED			; GO TURN MODE INDICATORS ON
  2808                              <1> 	;pop	ax			; RESTORE SCAN CODE
  2809 00000F97 58                  <1> 	pop	eax
  2810                              <1> K22B:
  2811 00000F98 3C52                <1> 	cmp	al, INS_KEY		; TEST FOR 1ST MAKE OF INSERT KEY
  2812                              <1>         ;jne	K26			; JUMP IF NOT INSERT KEY
  2813                              <1> 	; 24/12/2021
  2814 00000F9A 7405                <1> 	je	short K22C
  2815 00000F9C E983000000          <1> 	jmp	K26			; JUMP IF NOT INSERT KEY
  2816                              <1> K22C:
  2817 00000FA1 88C4                <1> 	mov	ah, al		        ; SCAN CODE IN BOTH HALVES OF AX
  2818 00000FA3 E999000000          <1>         jmp	K28			; FLAGS UPDATED, PROC. FOR BUFFER
  2819                              <1> 	;
  2820                              <1> 	;-----	BREAK SHIFT FOUND
  2821                              <1> K23:					; BREAK-SHIFT-FOUND
  2822 00000FA8 80FC10              <1> 	cmp	ah, SCROLL_SHIFT	; IS THIS A TOGGLE KEY
  2823 00000FAB F6D4                <1> 	not	ah			; INVERT MASK
  2824 00000FAD 7355                <1> 	jae	short K24		; YES, HANDLE BREAK TOGGLE
  2825 00000FAF 2025[03650000]      <1> 	and	[KB_FLAG], ah		; TURN OFF SHIFT BIT
  2826 00000FB5 80FCFB              <1> 	cmp	ah, ~CTL_SHIFT		; IS THIS ALT OR CTL?
  2827 00000FB8 7730                <1> 	ja	short K23D		; NO, ALL DONE
  2828                              <1> 	;
  2829 00000FBA F6C702              <1> 	test	bh, LC_E0		; 2ND ALT OR CTL?
  2830 00000FBD 7408                <1> 	jz	short K23A		; NO, HANSLE NORMALLY
  2831 00000FBF 2025[06650000]      <1> 	and 	[KB_FLAG_3], ah		; RESET BIT FOR RIGHT ALT OR CTL
  2832 00000FC5 EB08                <1> 	jmp	short K23B		; CONTINUE
  2833                              <1> K23A:
  2834 00000FC7 D2FC                <1> 	sar	ah, cl			; MOVE THE MASK BIT TWO POSITIONS
  2835 00000FC9 2025[04650000]      <1> 	and	[KB_FLAG_1], ah		; RESET BIT FOR LEFT ALT AND CTL
  2836                              <1> K23B:
  2837 00000FCF 88C4                <1> 	mov	ah, al			; SAVE SCAN CODE
  2838 00000FD1 A0[06650000]        <1> 	mov	al, [KB_FLAG_3]		; GET RIGHT ALT & CTRL FLAGS
  2839 00000FD6 D2E8                <1> 	shr	al, cl			; MOVE TO BITS 1 & 0
  2840 00000FD8 0A05[04650000]      <1> 	or	al, [KB_FLAG_1]		; PUT IN LEFT ALT & CTL FLAGS
  2841 00000FDE D2E0                <1> 	shl	al, cl			; MOVE BACK TO BITS 3 & 2
  2842 00000FE0 240C                <1> 	and	al, ALT_SHIFT+CTL_SHIFT ; FILTER OUT OTHER GARBAGE
  2843 00000FE2 0805[03650000]      <1> 	or	[KB_FLAG], al		; PUT RESULT IN THE REAL FLAGS	
  2844 00000FE8 88E0                <1> 	mov	al, ah
  2845                              <1> K23D:
  2846 00000FEA 3CB8                <1> 	cmp	al, ALT_KEY+80h		; IS THIS ALTERNATE SHIFT RELEASE
  2847 00000FEC 7536                <1> 	jne	short K26		; INTERRUPT RETURN
  2848                              <1> 	;	
  2849                              <1> 	;-----	ALTERNATE SHIFT KEY RELEASED, GET THE VALUE INTO BUFFER
  2850 00000FEE A0[07650000]        <1> 	mov	al, [ALT_INPUT]
  2851 00000FF3 B400                <1> 	mov	ah, 0			; SCAN CODE OF 0
  2852 00000FF5 8825[07650000]      <1> 	mov	[ALT_INPUT], ah 	; ZERO OUT THE FIELD
  2853 00000FFB 3C00                <1> 	cmp	al, 0			; WAS THE INPUT = 0?
  2854 00000FFD 7425                <1> 	je	short K26		; INTERRUPT_RETURN
  2855 00000FFF E9B8020000          <1>         jmp     K61                     ; IT WASN'T, SO PUT IN BUFFER
  2856                              <1> 	;
  2857                              <1> K24:					; BREAK-TOGGLE
  2858 00001004 2025[04650000]      <1> 	and	[KB_FLAG_1], ah 	; INDICATE NO LONGER DEPRESSED
  2859 0000100A EB18                <1> 	jmp	short K26		; INTERRUPT_RETURN
  2860                              <1> 	;
  2861                              <1> 	;-----	TEST FOR HOLD STATE
  2862                              <1> 					; AL, AH = SCAN CODE
  2863                              <1> K25:					; NO-SHIFT-FOUND
  2864 0000100C 3C80                <1> 	cmp	al, 80h			; TEST FOR BREAK KEY
  2865 0000100E 7314                <1> 	jae	short K26		; NOTHING FOR BREAK CHARS FROM HERE ON
  2866 00001010 F605[04650000]08    <1> 	test	byte [KB_FLAG_1], HOLD_STATE ; ARE WE IN HOLD STATE
  2867 00001017 7428                <1> 	jz	short K28		; BRANCH AROUND TEST IF NOT
  2868 00001019 3C45                <1> 	cmp	al, NUM_KEY
  2869 0000101B 7407                <1> 	je	short K26		; CAN'T END HOLD ON NUM_LOCK
  2870 0000101D 8025[04650000]F7    <1> 	and	byte [KB_FLAG_1], ~HOLD_STATE ; TURN OFF THE HOLD STATE BIT
  2871                              <1> 	;
  2872                              <1> K26:
  2873 00001024 8025[06650000]FC    <1> 	and	byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  2874                              <1> K26A:					; INTERRUPT-RETURN
  2875 0000102B FA                  <1> 	cli				; TURN OFF INTERRUPTS
  2876 0000102C B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  2877 0000102E E620                <1> 	out	20h, al	;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  2878                              <1> K27:					; INTERRUPT-RETURN-NO-EOI
  2879 00001030 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  2880 00001032 E8BC020000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  2881                              <1> K27A:
  2882 00001037 FA                  <1> 	cli				; DISABLE INTERRUPTS
  2883 00001038 07                  <1> 	pop	es			; RESTORE REGISTERS
  2884 00001039 1F                  <1> 	pop	ds
  2885 0000103A 5F                  <1> 	pop	edi
  2886 0000103B 5E                  <1> 	pop	esi
  2887 0000103C 5A                  <1> 	pop	edx
  2888 0000103D 59                  <1> 	pop	ecx
  2889 0000103E 5B                  <1> 	pop	ebx
  2890 0000103F 58                  <1> 	pop	eax
  2891                              <1> 	;pop	ebp
  2892 00001040 CF                  <1> 	iret				; RETURN
  2893                              <1> 
  2894                              <1> 	;-----	NOT IN	HOLD STATE
  2895                              <1> K28:					; NO-HOLD-STATE
  2896 00001041 3C58                <1> 	cmp	al, 88			; TEST FOR OUT-OF-RANGE SCAN CODES
  2897 00001043 77DF                <1> 	ja	short K26		; IGNORE IF OUT-OF-RANGE	
  2898                              <1> 	;
  2899 00001045 F6C308              <1> 	test	bl, ALT_SHIFT 		; ARE WE IN ALTERNATE SHIFT
  2900 00001048 740E                <1>         jz	short K28A		; IF NOT ALTERNATE
  2901                              <1>         ; 24/12/2021
  2902                              <1> 	;jz      K38
  2903                              <1> 	;
  2904 0000104A F6C710              <1> 	test	bh, KBX			; IS THIS THE ENCHANCED KEYBOARD?
  2905 0000104D 740E                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2906                              <1> 	; 28/02/2015
  2907 0000104F F605[04650000]04    <1> 	test	byte [KB_FLAG_1], SYS_SHIFT ; YES, IS SYSREQ KEY DOWN?
  2908 00001056 7405                <1> 	jz	short K29		; NO, ALT STATE IS REAL
  2909                              <1> 	; 24/12/2021
  2910                              <1> 	;jnz	K38			; YES, THIS IS PHONY ALT STATE 
  2911                              <1>         ;				; DUE TO PRESSING SYSREQ	
  2912 00001058 E9D1000000          <1> K28A:	jmp	K38
  2913                              <1> 	;
  2914                              <1> 	;-----	TEST FOR RESET KEY SEQUENCE (CTL ALT DEL)
  2915                              <1> K29:					; TEST-RESET
  2916 0000105D F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT ALSO?
  2917 00001060 740B                <1> 	jz	short K31		; NO_RESET
  2918 00001062 3C53                <1> 	cmp	al, DEL_KEY		; CTL-ALT STATE, TEST FOR DELETE KEY
  2919 00001064 7507                <1> 	jne	short K31		; NO_RESET, IGNORE
  2920                              <1> 	;
  2921                              <1> 	;-----	CTL-ALT-DEL HAS BEEN FOUND
  2922                              <1>  	; 26/08/2014
  2923                              <1> cpu_reset:
  2924                              <1> 	; IBM PC/AT ROM BIOS source code - 10/06/85 (TEST4.ASM - PROC_SHUTDOWN)
  2925                              <1> 	; Send FEh (system reset command) to the keyboard controller.
  2926 00001066 B0FE                <1> 	mov	al, SHUT_CMD		; SHUTDOWN COMMAND
  2927 00001068 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROL PORT
  2928                              <1> khere:
  2929 0000106A F4                  <1> 	hlt				; WAIT FOR 80286 RESET
  2930 0000106B EBFD                <1> 	jmp 	short khere		; INSURE HALT
  2931                              <1> 
  2932                              <1> 	;
  2933                              <1> 	;-----	IN ALTERNATE SHIFT, RESET NOT FOUND
  2934                              <1> K31:					; NO-RESET
  2935 0000106D 3C39                <1> 	cmp	al, 57			; TEST FOR SPACE KEY
  2936 0000106F 7507                <1> 	jne	short K311		; NOT THERE
  2937 00001071 B020                <1> 	mov	al, ' '			; SET SPACE CHAR
  2938 00001073 E936020000          <1>         jmp     K57                     ; BUFFER_FILL
  2939                              <1> K311:
  2940 00001078 3C0F                <1> 	cmp	al, 15			; TEST FOR TAB KEY
  2941 0000107A 7509                <1> 	jne	short K312		; NOT THERE
  2942 0000107C 66B800A5            <1> 	mov	ax, 0A500h		; SET SPECIAL CODE FOR ALT-TAB
  2943 00001080 E929020000          <1>         jmp     K57                     ; BUFFER_FILL
  2944                              <1> K312:
  2945 00001085 3C4A                <1> 	cmp	al, 74			; TEST FOR KEY PAD -
  2946 00001087 7471                <1>         je	short K37B              ; GO PROCESS
  2947 00001089 3C4E                <1> 	cmp	al, 78			; TEST FOR KEY PAD +
  2948 0000108B 746D                <1>         je	short K37B              ; GO PROCESS
  2949                              <1> 	;
  2950                              <1> 	;-----	LOOK FOR KEY PAD ENTRY
  2951                              <1> K32:					; ALT-KEY-PAD
  2952 0000108D BF[C4630000]        <1> 	mov	edi, K30		; ALT-INPUT-TABLE offset
  2953 00001092 B90A000000          <1> 	mov	ecx, 10			; LOOK FOR ENTRY USING KEYPAD
  2954 00001097 F2AE                <1> 	repne	scasb			; LOOK FOR MATCH
  2955 00001099 7523                <1> 	jne	short K33		; NO_ALT_KEYPAD
  2956 0000109B F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OF THE NEW KEYS?
  2957                              <1>         ;jnz	short K37C		; YES, JUMP, NOT NUMPAD KEY
  2958                              <1> 	; 24/12/2021
  2959 0000109E 751C                <1> 	jnz	short K32B
  2960 000010A0 81EF[C5630000]      <1> 	sub	edi, K30+1		; DI NOW HAS ENTRY VALUE
  2961 000010A6 A0[07650000]        <1> 	mov	al, [ALT_INPUT] 	; GET THE CURRENT BYTE
  2962 000010AB B40A                <1> 	mov	ah, 10			; MULTIPLY BY 10
  2963 000010AD F6E4                <1> 	mul	ah
  2964 000010AF 6601F8              <1> 	add	ax, di			; ADD IN THE LATEST ENTRY
  2965 000010B2 A2[07650000]        <1> 	mov	[ALT_INPUT], al 	; STORE IT AWAY
  2966                              <1> K32A:
  2967 000010B7 E968FFFFFF          <1>         jmp     K26                     ; THROW AWAY THAT KEYSTROKE
  2968                              <1> K32B:
  2969                              <1> 	; 24/12/2021
  2970 000010BC EB6A                <1> 	jmp	K37C
  2971                              <1> 	;
  2972                              <1> 	;-----	LOOK FOR SUPERSHIFT ENTRY
  2973                              <1> K33:					; NO-ALT-KEYPAD
  2974 000010BE C605[07650000]00    <1>         mov     byte [ALT_INPUT], 0     ; ZERO ANY PREVIOUS ENTRY INTO INPUT
  2975 000010C5 B91A000000          <1> 	mov	ecx, 26			; (DI),(ES) ALREADY POINTING
  2976 000010CA F2AE                <1> 	repne	scasb			; LOOK FOR MATCH IN ALPHABET
  2977 000010CC 7453                <1> 	je	short K37A		; MATCH FOUND, GO FILLL THE BUFFER
  2978                              <1> 	;
  2979                              <1> 	;-----	LOOK FOR TOP ROW OF ALTERNATE SHIFT
  2980                              <1> K34:					; ALT-TOP-ROW
  2981 000010CE 3C02                <1> 	cmp	al, 2			; KEY WITH '1' ON IT
  2982 000010D0 7228                <1> 	jb	short K37B		; MUST BE ESCAPE
  2983 000010D2 3C0D                <1> 	cmp	al, 13			; IS IT IN THE REGION
  2984 000010D4 7705                <1> 	ja	short K35		; NO, ALT SOMETHING ELSE
  2985 000010D6 80C476              <1> 	add	ah, 118			; CONVERT PSEUDO SCAN CODE TO RANGE
  2986 000010D9 EB46                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2987                              <1> 	;
  2988                              <1> 	;-----	TRANSLATE ALTERNATE SHIFT PSEUDO SCAN CODES
  2989                              <1> K35:					; ALT-FUNCTION
  2990 000010DB 3C57                <1> 	cmp	al, F11_M		; IS IT F11?	
  2991 000010DD 7209                <1> 	jb	short K35A ; 20/02/2015	; NO, BRANCH
  2992 000010DF 3C58                <1> 	cmp	al, F12_M		; IS IT F12?
  2993 000010E1 7705                <1> 	ja	short K35A ; 20/02/2015	; NO, BRANCH
  2994 000010E3 80C434              <1> 	add	ah, 52			; CONVERT TO PSEUDO SCAN CODE
  2995 000010E6 EB39                <1> 	jmp	short K37A		; GO FILL THE BUFFER
  2996                              <1> K35A:
  2997 000010E8 F6C702              <1> 	test	bh, LC_E0		; DO WE HAVE ONE OF THE NEW KEYS?
  2998 000010EB 7425                <1> 	jz	short K37		; NO, JUMP
  2999 000010ED 3C1C                <1> 	cmp	al, 28			; TEST FOR KEYPAD ENTER
  3000 000010EF 7510                <1>         jne     short K35B              ; NOT THERE
  3001 000010F1 66B800A6            <1> 	mov	ax, 0A600h		; SPECIAL CODE
  3002 000010F5 E9B4010000          <1> 	jmp	K57			; BUFFER FILL
  3003                              <1> K37B:
  3004 000010FA B0F0                <1> 	mov	al, 0F0h		; USE SPECIAL ASCII CODE
  3005 000010FC E9AD010000          <1> 	jmp     K57                     ; PUT IT IN THE BUFFER
  3006                              <1> K35B:
  3007 00001101 3C53                <1> 	cmp	al, 83			; TEST FOR DELETE KEY
  3008 00001103 7423                <1> 	je	short K37C		; HANDLE WITH OTHER EDIT KEYS
  3009 00001105 3C35                <1> 	cmp	al, 53			; TEST FOR KEYPAD /
  3010 00001107 75AE                <1> 	jne	short K32A		; NOT THERE, NO OTHER E0 SPECIALS	
  3011                              <1>         ; 24/12/2021
  3012                              <1> 	;jne	K26
  3013 00001109 66B800A4            <1> 	mov	ax, 0A400h		; SPECIAL CODE
  3014 0000110D E99C010000          <1> 	jmp	K57			; BUFFER FILL
  3015                              <1> K37:
  3016 00001112 3C3B                <1> 	cmp	al, 59			; TEST FOR FUNCTION KEYS (F1)
  3017 00001114 72E4                <1>         jb      short K37B		; NO FN, HANDLE W/OTHER EXTENDED
  3018 00001116 3C44                <1> 	cmp	al, 68			; IN KEYPAD REGION?
  3019                              <1>         ;ja	short K32A		; IF SO, IGNORE
  3020 00001118 0F8706FFFFFF        <1>         ja      K26
  3021 0000111E 80C42D              <1> 	add	ah, 45			; CONVERT TO PSEUDO SCAN CODE
  3022                              <1> K37A:
  3023 00001121 B000                <1> 	mov	al, 0			; ASCII CODE OF ZERO
  3024 00001123 E986010000          <1>         jmp     K57                     ; PUT IT IN THE BUFFER
  3025                              <1> K37C:
  3026 00001128 0450                <1> 	add	al, 80			; CONVERT SCAN CODE (EDIT KEYS)
  3027 0000112A 88C4                <1> 	mov	ah, al			; (SCAN CODE NOT IN AH FOR INSERT)
  3028 0000112C EBF3                <1> 	jmp     short K37A              ; PUT IT IN THE BUFFER
  3029                              <1> 	;
  3030                              <1> 	;-----	NOT IN ALTERNATE SHIFT
  3031                              <1> K38:					; NOT-ALT-SHIFT
  3032                              <1> 					; BL STILL HAS SHIFT FLAGS
  3033 0000112E F6C304              <1> 	test	bl, CTL_SHIFT 		; ARE WE IN CONTROL SHIFT?
  3034 00001131 7505                <1> 	jnz	short K38A		; YES, START PROCESSING	
  3035                              <1>         ;jz	K44                     ; NOT-CTL-SHIFT
  3036                              <1> 	; 24/12/2021
  3037 00001133 E9AB000000          <1> 	jmp	K44
  3038                              <1> 	;
  3039                              <1> 	;-----	CONTROL SHIFT, TEST SPECIAL CHARACTERS
  3040                              <1> 	;-----	TEST FOR BREAK
  3041                              <1> K38A:
  3042 00001138 3C46                <1> 	cmp	al, SCROLL_KEY		; TEST FOR BREAK
  3043 0000113A 7530                <1> 	jne	short K39		; JUMP, NO-BREAK
  3044 0000113C F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3045 0000113F 7405                <1> 	jz	short K38B		; NO, BREAK IS VALID	
  3046 00001141 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3047 00001144 7426                <1> 	jz	short K39		; NO-BREAK, TEST FOR PAUSE	
  3048                              <1> K38B:
  3049 00001146 8B1D[10650000]      <1> 	mov	ebx, [BUFFER_HEAD] 	; RESET BUFFER TO EMPTY
  3050 0000114C 891D[14650000]      <1> 	mov	[BUFFER_TAIL], ebx
  3051 00001152 C605[02650000]80    <1> 	mov	byte [BIOS_BREAK], 80h  ; TURN ON BIOS_BREAK BIT
  3052                              <1> 	;
  3053                              <1> 	;-----	ENABLE KEYBOARD
  3054 00001159 B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3055 0000115B E893010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3056                              <1> 	;
  3057                              <1> 	; CTRL+BREAK code here !!!
  3058                              <1> 	;INT	1BH			; BREAK INTERRUPT VECTOR
  3059                              <1> 	; 17/10/2015	
  3060 00001160 E85B220000          <1> 	call	ctrlbrk ; control+break subroutine
  3061                              <1> 	;
  3062                              <1> 	;sub	ax, ax			; PUT OUT DUMMY CHARACTER
  3063                              <1> 	; 24/12/2021
  3064 00001165 29C0                <1> 	sub	eax, eax
  3065 00001167 E942010000          <1> 	jmp     K57                     ; BUFFER_FILL
  3066                              <1> 	;
  3067                              <1> 	;-----	TEST FOR PAUSE
  3068                              <1> K39:					; NO_BREAK
  3069 0000116C F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3070 0000116F 7537                <1> 	jnz	short K41		; YES, THEN THIS CAN'T BE PAUSE	
  3071 00001171 3C45                <1> 	cmp	al, NUM_KEY		; LOOK FOR PAUSE KEY
  3072 00001173 7533                <1> 	jne	short K41		; NO-PAUSE
  3073                              <1> K39P:
  3074 00001175 800D[04650000]08    <1> 	or	byte [KB_FLAG_1], HOLD_STATE ; TURN ON THE HOLD FLAG
  3075                              <1> 	;
  3076                              <1> 	;-----	ENABLE KEYBOARD
  3077 0000117C B0AE                <1> 	mov	al, ENA_KBD		; ENABLE KEYBOARD
  3078 0000117E E870010000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3079                              <1> K39A:
  3080 00001183 B020                <1> 	mov	al, EOI			; END OF INTERRUPT TO CONTROL PORT
  3081 00001185 E620                <1> 	out	20h, al ;out INTA00, al	; ALLOW FURTHER KEYSTROKE INTERRUPTS
  3082                              <1> 	;
  3083                              <1> 	;-----	DURING PAUSE INTERVAL, TURN COLOR CRT BACK ON
  3084 00001187 803D[00650000]07    <1>         cmp     byte [CRT_MODE], 7      ; IS THIS BLACK AND WHITE CARD
  3085 0000118E 740A                <1>         je      short K40              	; YES, NOTHING TO DO
  3086 00001190 66BAD803            <1> 	mov	dx, 03D8h		; PORT FOR COLOR CARD
  3087 00001194 A0[01650000]        <1>         mov     al, [CRT_MODE_SET] 	; GET THE VALUE OF THE CURRENT MODE
  3088 00001199 EE                  <1> 	out	dx, al			; SET THE CRT MODE, SO THAT CRT IS ON
  3089                              <1> 	;
  3090                              <1> K40:					; PAUSE-LOOP
  3091 0000119A F605[04650000]08    <1>         test    byte [KB_FLAG_1], HOLD_STATE ; CHECK HOLD STATE FLAG
  3092 000011A1 75F7                <1> 	jnz	short K40		; LOOP UNTIL FLAG TURNED OFF
  3093                              <1> 	;
  3094 000011A3 E988FEFFFF          <1>         jmp     K27                     ; INTERRUPT_RETURN_NO_EOI
  3095                              <1>         ;
  3096                              <1> 	;-----	TEST SPECIAL CASE KEY 55
  3097                              <1> K41:					; NO-PAUSE
  3098 000011A8 3C37                <1> 	cmp	al, 55			; TEST FOR */PRTSC KEY
  3099 000011AA 7513                <1> 	jne	short K42		; NOT-KEY-55
  3100 000011AC F6C710              <1> 	test	bh, KBX			; IS THIS THE ENHANCED KEYBOARD?
  3101 000011AF 7405                <1> 	jz	short K41A		; NO, CTL-PRTSC IS VALID	
  3102 000011B1 F6C702              <1> 	test	bh, LC_E0		; YES, WAS LAST CODE AN E0?
  3103 000011B4 7421                <1> 	jz	short K42B		; NO, TRANSLATE TO A FUNCTION
  3104                              <1> K41A:	
  3105 000011B6 66B80072            <1> 	mov	ax, 114*256		; START/STOP PRINTING SWITCH
  3106 000011BA E9EF000000          <1>         jmp     K57                     ; BUFFER_FILL
  3107                              <1> 	;
  3108                              <1> 	;-----	SET UP TO TRANSLATE CONTROL SHIFT
  3109                              <1> K42:					; NOT-KEY-55
  3110 000011BF 3C0F                <1> 	cmp	al, 15			; IS IT THE TAB KEY?
  3111 000011C1 7414                <1> 	je	short K42B		; YES, XLATE TO FUNCTION CODE
  3112 000011C3 3C35                <1> 	cmp	al, 53			; IS IT THE / KEY?
  3113 000011C5 750E                <1> 	jne	short K42A		; NO, NO MORE SPECIAL CASES	
  3114 000011C7 F6C702              <1> 	test	bh, LC_E0		; YES, IS IT FROM THE KEY PAD?
  3115 000011CA 7409                <1> 	jz	short K42A		; NO, JUST TRANSLATE
  3116 000011CC 66B80095            <1> 	mov	ax, 9500h		; YES, SPECIAL CODE FOR THIS ONE
  3117 000011D0 E9D9000000          <1> 	jmp	K57			; BUFFER FILL	
  3118                              <1> K42A:
  3119                              <1> 	;mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3120 000011D5 3C3B                <1> 	cmp	al, 59			; IS IT IN CHARACTER TABLE?
  3121                              <1>         ;jb	short K45F              ; YES, GO TRANSLATE CHAR
  3122                              <1> 	;;jb	K56 ; 20/02/2015
  3123                              <1> 	;;jmp	K64 ; 20/02/2015
  3124                              <1> K42B:
  3125 000011D7 BB[F8630000]        <1> 	mov	ebx, _K8		; SET UP TO TRANSLATE CTL
  3126                              <1> 	;;jmp	K64
  3127                              <1> 	;jb	K56 ;; 20/02/2015	
  3128                              <1> 	; 24/12/2021
  3129 000011DC 7267                <1> 	jb	short K45F
  3130 000011DE E9B9000000          <1> 	jmp	K64	
  3131                              <1>         ;
  3132                              <1> 	;-----	NOT IN CONTROL SHIFT
  3133                              <1> K44:					; NOT-CTL-SHIFT
  3134 000011E3 3C37                <1> 	cmp	al, 55			; PRINT SCREEN KEY?
  3135 000011E5 7528                <1> 	jne	short K45		; NOT PRINT SCREEN
  3136 000011E7 F6C710              <1> 	test	bh, KBX			; IS THIS ENHANCED KEYBOARD?
  3137 000011EA 7407                <1> 	jz	short K44A		; NO, TEST FOR SHIFT STATE	
  3138 000011EC F6C702              <1> 	test	bh, LC_E0		; YES, LAST CODE A MARKER?
  3139 000011EF 7507                <1> 	jnz	short K44B		; YES, IS PRINT SCREEN
  3140 000011F1 EB41                <1> 	jmp	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3141                              <1> K44A:
  3142 000011F3 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; NOT 101 KBD, SHIFT KEY DOWN?
  3143 000011F6 743C                <1> 	jz	short K45C		; NO, TRANSLATE TO '*' CHARACTER
  3144                              <1> 	;
  3145                              <1> 	;-----	ISSUE INTERRUPT TO INDICATE PRINT SCREEN FUNCTION
  3146                              <1> K44B:
  3147 000011F8 B0AE                <1> 	mov	al, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3148 000011FA E8F4000000          <1> 	call	SHIP_IT			; EXECUTE ENABLE
  3149 000011FF B020                <1> 	mov	al, EOI			; END OF CURRENT INTERRUPT
  3150 00001201 E620                <1> 	out	20h, al ;out INTA00, al	; SO FURTHER THINGS CAN HAPPEN
  3151                              <1> 	; Print Screen !!!		; ISSUE PRINT SCREEN INTERRUPT (INT 05h)
  3152                              <1> 	;PUSH 	BP			; SAVE POINTER
  3153                              <1> 	;INT 	5H			; ISSUE PRINT SCREEN INTERRUPT
  3154                              <1> 	;POP	BP			; RESTORE POINTER
  3155 00001203 8025[06650000]FC    <1>         and     byte [KB_FLAG_3], ~(LC_E0+LC_E1) ; ZERO OUT THESE FLAGS
  3156 0000120A E921FEFFFF          <1>         jmp     K27                     ; GO BACK WITHOUT EOI OCCURRING
  3157                              <1> 	;
  3158                              <1> 	;-----	HANDLE IN-CORE KEYS
  3159                              <1> K45:					; NOT-PRINT-SCREEN
  3160 0000120F 3C3A                <1> 	cmp	al, 58			; TEST FOR IN-CORE AREA
  3161 00001211 7734                <1> 	ja	short K46		; JUMP IF NOT
  3162 00001213 3C35                <1> 	cmp	al, 53			; IS THIS THE '/' KEY?
  3163 00001215 7505                <1> 	jne	short K45A		; NO, JUMP
  3164 00001217 F6C702              <1> 	test	bh, LC_E0		; WAS THE LAST CODE THE MARKER?
  3165 0000121A 7518                <1> 	jnz	short K45C		; YES, TRANSLATE TO CHARACTER
  3166                              <1> K45A:
  3167 0000121C B91A000000          <1> 	mov	ecx, 26			; LENGHT OF SEARCH
  3168 00001221 BF[CE630000]        <1> 	mov	edi, K30+10		; POINT TO TABLE OF A-Z CHARS
  3169 00001226 F2AE                <1> 	repne	scasb			; IS THIS A LETTER KEY?
  3170                              <1> 		; 20/02/2015
  3171 00001228 7505                <1> 	jne	short K45B              ; NO, SYMBOL KEY
  3172                              <1> 	;
  3173 0000122A F6C340              <1> 	test	bl, CAPS_STATE		; ARE WE IN CAPS_LOCK?
  3174 0000122D 750C                <1> 	jnz	short K45D		; TEST FOR SURE
  3175                              <1> K45B:
  3176 0000122F F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3177 00001232 750C                <1> 	jnz	short K45E		; YES, UPPERCASE
  3178                              <1> 					; NO, LOWERCASE
  3179                              <1> K45C:
  3180 00001234 BB[50640000]        <1> 	mov	ebx, K10		; TRANSLATE TO LOWERCASE LETTERS
  3181 00001239 EB51                <1> 	jmp	short K56	
  3182                              <1> K45D:					; ALMOST-CAPS-STATE
  3183 0000123B F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; CL ON. IS SHIFT ON, TOO?
  3184 0000123E 75F4                <1> 	jnz	short K45C		; SHIFTED TEMP OUT OF CAPS STATE
  3185                              <1> K45E:
  3186 00001240 BB[A8640000]        <1> 	mov	ebx, K11		; TRANSLATE TO UPPER CASE LETTERS
  3187 00001245 EB45                <1> K45F:	jmp	short K56
  3188                              <1> 	;
  3189                              <1> 	;-----	TEST FOR KEYS F1 - F10
  3190                              <1> K46:					; NOT IN-CORE AREA
  3191 00001247 3C44                <1> 	cmp	al, 68			; TEST FOR F1 - F10
  3192                              <1> 	;ja	short K47		; JUMP IF NOT
  3193                              <1> 	;jmp	short K53		; YES, GO DO FN KEY PROCESS			
  3194 00001249 7635                <1> 	jna	short K53		
  3195                              <1> 	;
  3196                              <1> 	;-----	HANDLE THE NUMERIC PAD KEYS
  3197                              <1> K47:					; NOT F1 - F10
  3198 0000124B 3C53                <1> 	cmp	al, 83			; TEST NUMPAD KEYS
  3199 0000124D 772D                <1> 	ja	short K52		; JUMP IF NOT
  3200                              <1> 	;
  3201                              <1> 	;-----	KEYPAD KEYS, MUST TEST NUM LOCK FOR DETERMINATION
  3202                              <1> K48:
  3203 0000124F 3C4A                <1> 	cmp	al , 74			; SPECIAL CASE FOR MINUS
  3204 00001251 74ED                <1> 	je	short K45E		; GO TRANSLATE
  3205 00001253 3C4E                <1> 	cmp	al , 78			; SPECIAL CASE FOR PLUS
  3206 00001255 74E9                <1> 	je	short K45E		; GO TRANSLATE
  3207 00001257 F6C702              <1> 	test	bh, LC_E0		; IS THIS ONE OFTHE NEW KEYS?
  3208 0000125A 750A                <1> 	jnz	short K49		; YES, TRANSLATE TO BASE STATE
  3209                              <1> 	;		
  3210 0000125C F6C320              <1> 	test 	bl, NUM_STATE		; ARE WE IN NUM LOCK
  3211 0000125F 7514                <1> 	jnz	short K50		; TEST FOR SURE
  3212 00001261 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; ARE WE IN SHIFT STATE?
  3213                              <1> 	;jnz	short K51		; IF SHIFTED, REALLY NUM STATE
  3214 00001264 75DA                <1> 	jnz	short K45E
  3215                              <1> 	;
  3216                              <1> 	;-----	BASE CASE FOR KEYPAD
  3217                              <1> K49:					
  3218 00001266 3C4C                <1> 	cmp	al, 76			; SPECIAL CASE FOR BASE STATE 5
  3219 00001268 7504                <1> 	jne	short K49A		; CONTINUE IF NOT KEYPAD 5
  3220 0000126A B0F0                <1> 	mov	al, 0F0h		; SPECIAL ASCII CODE	
  3221 0000126C EB40                <1> 	jmp	short K57		; BUFFER FILL
  3222                              <1> K49A:
  3223 0000126E BB[50640000]        <1> 	mov	ebx, K10		; BASE CASE TABLE	
  3224 00001273 EB27                <1> 	jmp	short K64		; CONVERT TO PSEUDO SCAN
  3225                              <1> 	;
  3226                              <1> 	;-----	MIGHT BE NUM LOCK, TEST SHIFT STATUS
  3227                              <1> K50:					; ALMOST-NUM-STATE
  3228 00001275 F6C303              <1>         test    bl, LEFT_SHIFT+RIGHT_SHIFT
  3229 00001278 75EC                <1> 	jnz 	short K49		; SHIFTED TEMP OUT OF NUM STATE
  3230 0000127A EBC4                <1> K51:	jmp	short K45E		; REALLY NUM STATE
  3231                              <1> 	;
  3232                              <1> 	;-----	TEST FOR THE NEW KEYS ON WT KEYBOARDS 
  3233                              <1> K52:					; NOT A NUMPAD KEY
  3234 0000127C 3C56                <1> 	cmp	al, 86			; IS IT THE NEW WT KEY?
  3235                              <1> 	;jne	short K53		; JUMP IF NOT
  3236                              <1> 	;jmp	short K45B		; HANDLE WITH REST OF LETTER KEYS
  3237 0000127E 74AF                <1> 	je	short K45B		
  3238                              <1> 	;
  3239                              <1> 	;-----	MUST BE F11 OR F12 
  3240                              <1> K53:					; F1 - F10 COME HERE, TOO
  3241 00001280 F6C303              <1> 	test	bl, LEFT_SHIFT+RIGHT_SHIFT ; TEST SHIFT STATE
  3242 00001283 74E1                <1> 	jz	short K49		; JUMP, LOWER CASE PSEUDO SC'S
  3243                              <1> 		; 20/02/2015 
  3244 00001285 BB[A8640000]        <1> 	mov	ebx, K11		; UPPER CASE PSEUDO SCAN CODES
  3245 0000128A EB10                <1> 	jmp	short K64		; TRANSLATE SCAN
  3246                              <1> 	;
  3247                              <1> 	;-----	TRANSLATE THE CHARACTER
  3248                              <1> K56:					; TRANSLATE-CHAR
  3249 0000128C FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3250 0000128E D7                  <1> 	xlat    			; CONVERT THE SCAN CODE TO ASCII
  3251 0000128F F605[06650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3252 00001296 7416                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3253 00001298 B4E0                <1> 	mov	ah, MC_E0		; YES, PUT SPECIAL MARKER IN AH
  3254 0000129A EB12                <1> 	jmp	short K57		; PUT IT INTO THE BUFFER	
  3255                              <1> 	;
  3256                              <1> 	;-----	TRANSLATE SCAN FOR PSEUDO SCAN CODES
  3257                              <1> K64:					; TRANSLATE-SCAN-ORGD
  3258 0000129C FEC8                <1> 	dec	al			; CONVERT ORIGIN
  3259 0000129E D7                  <1>        	xlat    	                ; CTL TABLE SCAN
  3260 0000129F 88C4                <1> 	mov	ah, al			; PUT VALUE INTO AH
  3261 000012A1 B000                <1> 	mov	al, 0			; ZERO ASCII CODE
  3262 000012A3 F605[06650000]02    <1> 	test	byte [KB_FLAG_3], LC_E0	; IS THIS A NEW KEY?
  3263 000012AA 7402                <1> 	jz	short K57		; NO, GO FILL BUFFER
  3264 000012AC B0E0                <1> 	mov	al, MC_E0		; YES, PUT SPECIAL MARKER IN AL
  3265                              <1> 	;
  3266                              <1> 	;-----	PUT CHARACTER INTO BUFFER
  3267                              <1> K57:					; BUFFER_FILL
  3268 000012AE 3CFF                <1> 	cmp	al, -1			; IS THIS AN IGNORE CHAR
  3269 000012B0 7405                <1>         je	short K59		; YES, DO NOTHING WITH IT
  3270                              <1> 	; 24/12/2021
  3271                              <1> 	;je	K26			; YES, DO NOTHING WITH IT
  3272 000012B2 80FCFF              <1> 	cmp	ah, -1			; LOOK FOR -1 PSEUDO SCAN
  3273                              <1> 	; 24/12/2021
  3274 000012B5 7505                <1>         jne	short K61		; NEAR_INTERRUPT_RETURN
  3275                              <1> 	;je	K26			; INTERRUPT_RETURN
  3276                              <1> K59:					; NEAR_INTERRUPT_RETURN
  3277 000012B7 E968FDFFFF          <1> 	jmp	K26			; INTERRUPT_RETURN
  3278                              <1> K61:					; NOT-CAPS-STATE
  3279 000012BC 8B1D[14650000]      <1> 	mov	ebx, [BUFFER_TAIL] 	; GET THE END POINTER TO THE BUFFER
  3280 000012C2 89DE                <1> 	mov	esi, ebx		; SAVE THE VALUE
  3281 000012C4 E8AAFAFFFF          <1> 	call	_K4			; ADVANCE THE TAIL
  3282 000012C9 3B1D[10650000]      <1> 	cmp	ebx, [BUFFER_HEAD] 	; HAS THE BUFFER WRAPPED AROUND
  3283 000012CF 740E                <1> 	je	short K62		; BUFFER_FULL_BEEP
  3284 000012D1 668906              <1> 	mov	[esi], ax		; STORE THE VALUE
  3285 000012D4 891D[14650000]      <1> 	mov	[BUFFER_TAIL], ebx 	; MOVE THE POINTER UP
  3286 000012DA E945FDFFFF          <1> 	jmp	K26
  3287                              <1> 	;;cli				; TURN OFF INTERRUPTS
  3288                              <1> 	;;mov	al, EOI			; END OF INTERRUPT COMMAND
  3289                              <1> 	;;out	INTA00, al		; SEND COMMAND TO INTERRUPT CONTROL PORT
  3290                              <1> 	;MOV	AL, ENA_KBD		; INSURE KEYBOARD IS ENABLED
  3291                              <1> 	;CALL	SHIP_IT			; EXECUTE ENABLE
  3292                              <1> 	;MOV	AX, 9102H		; MOVE IN POST CODE & TYPE
  3293                              <1> 	;INT	15H			; PERFORM OTHER FUNCTION
  3294                              <1> 	;;and	byte [KB_FLAG_3],~(LC_E0+LC_E1) ; RESET LAST CHAR H.C. FLAG
  3295                              <1> 	;JMP	K27A			; INTERRUPT_RETURN
  3296                              <1> 	;;jmp   K27                    
  3297                              <1> 	;
  3298                              <1> 	;-----	BUFFER IS FULL SOUND THE BEEPER
  3299                              <1> K62:
  3300 000012DF B020                <1> 	mov	al, EOI			; ENABLE INTERRUPT CONTROLLER CHIP
  3301 000012E1 E620                <1> 	out	INTA00, al
  3302 000012E3 66B9A602            <1> 	mov	cx, 678			; DIVISOR FOR 1760 HZ
  3303 000012E7 B304                <1> 	mov	bl, 4			; SHORT BEEP COUNT (1/16 + 1/64 DELAY)
  3304 000012E9 E883010000          <1> 	call	beep			; GO TO COMMON BEEP HANDLER
  3305 000012EE E93DFDFFFF          <1> 	jmp     K27			; EXIT   
  3306                              <1> 
  3307                              <1> SHIP_IT:
  3308                              <1> 	;---------------------------------------------------------------------------------
  3309                              <1> 	; SHIP_IT
  3310                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3311                              <1> 	;	TO THE KEYBOARD CONTROLLER.
  3312                              <1> 	;---------------------------------------------------------------------------------
  3313                              <1> 	;
  3314                              <1> 	;push	ax			; SAVE DATA TO SEND
  3315                              <1> 	; 24/12/2021
  3316 000012F3 50                  <1> 	push	eax
  3317                              <1> 	;-----	WAIT FOR COMMAND TO ACCEPTED
  3318 000012F4 FA                  <1> 	cli				; DISABLE INTERRUPTS TILL DATA SENT
  3319                              <1> 	; xor	ecx, ecx		; CLEAR TIMEOUT COUNTER
  3320 000012F5 B900000100          <1> 	mov	ecx, 10000h			
  3321                              <1> S10:
  3322 000012FA E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD CONTROLLER STATUS
  3323 000012FC A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ITS INPUT BUFFER BUSY
  3324 000012FE E0FA                <1> 	loopnz	S10			; WAIT FOR COMMAND TO BE ACCEPTED
  3325                              <1> 
  3326                              <1> 	;pop	ax			; GET DATA TO SEND
  3327                              <1> 	; 24/12/2021
  3328 00001300 58                  <1> 	pop	eax
  3329 00001301 E664                <1> 	out	STATUS_PORT, al		; SEND TO KEYBOARD CONTROLLER
  3330 00001303 FB                  <1> 	sti				; ENABLE INTERRUPTS AGAIN
  3331 00001304 C3                  <1> 	retn				; RETURN TO CALLER
  3332                              <1> 
  3333                              <1> SND_DATA:
  3334                              <1> 	; ---------------------------------------------------------------------------------
  3335                              <1> 	; SND_DATA
  3336                              <1> 	;	THIS ROUTINES HANDLES TRANSMISSION OF COMMAND AND DATA BYTES
  3337                              <1> 	;	TO THE KEYBOARD AND RECEIPT OF ACKNOWLEDGEMENTS. IT ALSO
  3338                              <1> 	;	HANDLES ANY RETRIES IF REQUIRED
  3339                              <1> 	; ---------------------------------------------------------------------------------
  3340                              <1> 	;
  3341                              <1> 	;push	ax			; SAVE REGISTERS
  3342                              <1> 	;push	bx
  3343                              <1> 	; 24/12/2021
  3344 00001305 50                  <1> 	push	eax
  3345 00001306 53                  <1> 	push	ebx
  3346 00001307 51                  <1> 	push	ecx
  3347 00001308 88C7                <1> 	mov	bh, al			; SAVE TRANSMITTED BYTE FOR RETRIES
  3348 0000130A B303                <1> 	mov	bl, 3			; LOAD RETRY COUNT
  3349                              <1> SD0:
  3350 0000130C FA                  <1> 	cli				; DISABLE INTERRUPTS
  3351 0000130D 8025[05650000]CF    <1> 	and	byte [KB_FLAG_2], ~(KB_FE+KB_FA) ; CLEAR ACK AND RESEND FLAGS
  3352                              <1> 	;
  3353                              <1> 	;-----	WAIT FOR COMMAND TO BE ACCEPTED
  3354 00001314 B900000100          <1> 	mov	ecx, 10000h		; MAXIMUM WAIT COUNT
  3355                              <1> SD5:
  3356 00001319 E464                <1> 	in	al, STATUS_PORT		; READ KEYBOARD PROCESSOR STATUS PORT
  3357 0000131B A802                <1> 	test	al, INPT_BUF_FULL	; CHECK FOR ANY PENDING COMMAND
  3358 0000131D E0FA                <1> 	loopnz	SD5			; WAIT FOR COMMAND TO BE ACCEPTED
  3359                              <1> 	;
  3360 0000131F 88F8                <1> 	mov	al, bh			; REESTABLISH BYTE TO TRANSMIT
  3361 00001321 E660                <1> 	out	PORT_A, al		; SEND BYTE
  3362 00001323 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3363                              <1> 	;mov	cx, 01A00h		; LOAD COUNT FOR 10 ms+
  3364 00001324 B9FFFF0000          <1> 	mov	ecx, 0FFFFh
  3365                              <1> SD1:
  3366 00001329 F605[05650000]30    <1> 	test	byte [KB_FLAG_2], KB_FE+KB_FA ; SEE IF EITHER BIT SET
  3367 00001330 750F                <1> 	jnz	short SD3		; IF SET, SOMETHING RECEIVED GO PROCESS
  3368 00001332 E2F5                <1> 	loop	SD1			; OTHERWISE WAIT
  3369                              <1> SD2:
  3370 00001334 FECB                <1> 	dec	bl			; DECREMENT RETRY COUNT
  3371 00001336 75D4                <1> 	jnz	short SD0		; RETRY TRANSMISSION
  3372 00001338 800D[05650000]80    <1> 	or	byte [KB_FLAG_2], KB_ERR ; TURN ON TRANSMIT ERROR FLAG
  3373 0000133F EB09                <1> 	jmp	short SD4		; RETRIES EXHAUSTED FORGET TRANSMISSION
  3374                              <1> SD3:
  3375 00001341 F605[05650000]10    <1> 	test	byte [KB_FLAG_2], KB_FA ; SEE IF THIS IS AN ACKNOWLEDGE
  3376 00001348 74EA                <1> 	jz	short SD2		; IF NOT, GO RESEND
  3377                              <1> SD4:	
  3378 0000134A 59                  <1> 	pop	ecx			; RESTORE REGISTERS
  3379                              <1> 	;pop	bx
  3380                              <1> 	;pop	ax
  3381                              <1> 	; 24/12/2021
  3382 0000134B 5B                  <1> 	pop	ebx
  3383 0000134C 58                  <1> 	pop	eax
  3384 0000134D C3                  <1> 	retn				; RETURN, GOOD TRANSMISSION
  3385                              <1> 
  3386                              <1> SND_LED:
  3387                              <1> 	; ---------------------------------------------------------------------------------
  3388                              <1> 	; SND_LED
  3389                              <1> 	;	THIS ROUTINES TURNS ON THE MODE INDICATORS.
  3390                              <1> 	;
  3391                              <1> 	;----------------------------------------------------------------------------------
  3392                              <1> 	;
  3393 0000134E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3394 0000134F F605[05650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3395 00001356 755F                <1> 	jnz 	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3396                              <1> 	;
  3397 00001358 800D[05650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3398 0000135F B020                <1> 	mov	al, EOI			; END OF INTERRUPT COMMAND
  3399 00001361 E620                <1> 	out	20h, al ;out INTA00, al	; SEND COMMAND TO INTERRUPT CONTROL PORT
  3400 00001363 EB11                <1> 	jmp	short SL0		; GO SEND MODE INDICATOR COMMAND
  3401                              <1> SND_LED1:
  3402 00001365 FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3403 00001366 F605[05650000]40    <1> 	test	byte [KB_FLAG_2], KB_PR_LED ; CHECK FOR MODE INDICATOR UPDATE
  3404 0000136D 7548                <1> 	jnz	short SL1		; DON'T UPDATE AGAIN IF UPDATE UNDERWAY
  3405                              <1> 	;
  3406 0000136F 800D[05650000]40    <1> 	or	byte [KB_FLAG_2], KB_PR_LED ; TURN ON UPDATE IN PROCESS
  3407                              <1> SL0:
  3408 00001376 B0ED                <1> 	mov	al, LED_CMD		; LED CMD BYTE
  3409 00001378 E888FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3410 0000137D FA                  <1> 	cli
  3411 0000137E E836000000          <1> 	call	MAKE_LED		; GO FORM INDICATOR DATA BYTE
  3412 00001383 8025[05650000]F8    <1> 	and	byte [KB_FLAG_2], 0F8h	; ~KB_LEDS ; CLEAR MODE INDICATOR BITS
  3413 0000138A 0805[05650000]      <1> 	or	[KB_FLAG_2], al 	; SAVE PRESENT INDICATORS FOR NEXT TIME
  3414 00001390 F605[05650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3415 00001397 750F                <1> 	jnz	short SL2		; IF SO, BYPASS SECOND BYTE TRANSMISSION
  3416                              <1> 	;
  3417 00001399 E867FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3418 0000139E FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3419 0000139F F605[05650000]80    <1> 	test	byte [KB_FLAG_2], KB_ERR ; TRANSMIT ERROR DETECTED
  3420 000013A6 7408                <1> 	jz	short SL3		; IF NOT, DON'T SEND AN ENABLE COMMAND
  3421                              <1> SL2:
  3422 000013A8 B0F4                <1> 	mov	al, KB_ENABLE		; GET KEYBOARD CSA ENABLE COMMAND
  3423 000013AA E856FFFFFF          <1> 	call	SND_DATA		; SEND DATA TO KEYBOARD
  3424 000013AF FA                  <1> 	cli				; TURN OFF INTERRUPTS
  3425                              <1> SL3:
  3426 000013B0 8025[05650000]3F    <1> 	and	byte [KB_FLAG_2], ~(KB_PR_LED+KB_ERR) ; TURN OFF MODE INDICATOR
  3427                              <1> SL1:					; UPDATE AND TRANSMIT ERROR FLAG
  3428 000013B7 FB                  <1> 	sti				; ENABLE INTERRUPTS
  3429 000013B8 C3                  <1> 	retn				; RETURN TO CALLER
  3430                              <1> 
  3431                              <1> MAKE_LED:
  3432                              <1> 	;---------------------------------------------------------------------------------
  3433                              <1> 	; MAKE_LED
  3434                              <1> 	;	THIS ROUTINES FORMS THE DATA BYTE NECESSARY TO TURN ON/OFF
  3435                              <1> 	;	THE MODE INDICATORS.
  3436                              <1> 	;---------------------------------------------------------------------------------
  3437                              <1> 	;
  3438                              <1> 	;push 	cx			; SAVE CX
  3439 000013B9 A0[03650000]        <1> 	mov	al, [KB_FLAG]		; GET CAPS & NUM LOCK INDICATORS
  3440 000013BE 2470                <1> 	and	al, CAPS_STATE+NUM_STATE+SCROLL_STATE ; ISOLATE INDICATORS
  3441                              <1> 	;mov	cl, 4			; SHIFT COUNT
  3442                              <1> 	;rol	al, cl			; SHIFT BITS OVER TO TURN ON INDICATORS
  3443 000013C0 C0C004              <1> 	rol	al, 4 ; 20/02/2015
  3444 000013C3 2407                <1> 	and	al, 07h			; MAKE SURE ONLY MODE BITS ON
  3445                              <1> 	;pop	cx
  3446 000013C5 C3                  <1> 	retn				; RETURN TO CALLER
  3447                              <1> 
  3448                              <1> ; % include 'kybdata.inc'   ; KEYBOARD DATA ; 11/03/2015
  3449                              <1> 
  3450                              <1> ; /// End Of KEYBOARD FUNCTIONS ///
  1874                                  
  1875                                  %include 'video.inc' ; 07/03/2015
  1876                              <1> ; Retro UNIX 386 v1 Kernel - VIDEO.INC
  1877                              <1> ; Last Modification: 26/02/2022
  1878                              <1> ;		  (Video Data is in 'VIDATA.INC')
  1879                              <1> ;
  1880                              <1> ; ///////// VIDEO (CGA) FUNCTIONS ///////////////
  1881                              <1> 
  1882                              <1> ; 07/02/2022
  1883                              <1> ; 02/02/2022 (simplified scroll up)
  1884                              <1> ; 16/01/2016
  1885                              <1> ; 30/06/2015
  1886                              <1> ; 27/06/2015
  1887                              <1> ; 11/03/2015
  1888                              <1> ; 02/09/2014
  1889                              <1> ; 30/08/2014
  1890                              <1> ; VIDEO FUNCTIONS
  1891                              <1> ; (write_tty - Retro UNIX 8086 v1 - U9.ASM, 01/02/2014)
  1892                              <1> 
  1893                              <1> write_tty:
  1894                              <1> 	; 02/02/2022
  1895                              <1> 	; 13/08/2015
  1896                              <1> 	; 02/09/2014
  1897                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  1898                              <1> 	; 01/02/2014 (Retro UNIX 8086 v1 - last update)
  1899                              <1> 	; 03/12/2013 (Retro UNIX 8086 v1 - beginning)	
  1900                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  1901                              <1> 	;
  1902                              <1> 	; INPUT -> AH = Color (Forecolor, Backcolor)
  1903                              <1> 	;	   AL = Character to be written
  1904                              <1> 	;	   EBX = Video Page (0 to 7)
  1905                              <1> 	;	   (BH = 0 --> Video Mode 3)
  1906                              <1> 
  1907                              <1> RVRT	equ	00001000b	; VIDEO VERTICAL RETRACE BIT
  1908                              <1> RHRZ	equ	00000001b	; VIDEO HORIZONTAL RETRACE BIT
  1909                              <1> 
  1910                              <1> ; Derived from "WRITE_TTY" procedure of IBM "pc-at" rombios source code
  1911                              <1> ; (06/10/1985), 'video.asm', INT 10H, VIDEO_IO
  1912                              <1> ;
  1913                              <1> ; 06/10/85  VIDEO DISPLAY BIOS
  1914                              <1> ;
  1915                              <1> ;--- WRITE_TTY ------------------------------------------------------------------
  1916                              <1> ;										:
  1917                              <1> ;   THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE TO THE			:
  1918                              <1> ;   VIDEO CARDS. THE INPUT CHARACTER IS WRITTEN TO THE CURRENT			:
  1919                              <1> ;   CURSOR POSITION, AND THE CURSOR IS MOVED TO THE NEXT POSITION.		:
  1920                              <1> ;   IF THE CURSOR LEAVES THE LAST COLUMN OF THE FIELD, THE COLUMN		:
  1921                              <1> ;   IS SET TO ZERO, AND THE ROW VALUE IS INCREMENTED. IF THE ROW		:
  1922                              <1> ;   ROW VALUE LEAVES THE FIELD, THE CURSOR IS PLACED ON THE LAST ROW,		:
  1923                              <1> ;   FIRST COLUMN, AND THE ENTIRE SCREEN IS SCROLLED UP ONE LINE.		:
  1924                              <1> ;   WHEN THE SCREEN IS SCROLLED UP, THE ATTRIBUTE FOR FILLING THE		:
  1925                              <1> ;   NEWLY BLANKED LINE IS READ FROM THE CURSOR POSITION ON THE PREVIOUS		:
  1926                              <1> ;   LINE BEFORE THE SCROLL, IN CHARACTER MODE. IN GRAPHICS MODE,		:
  1927                              <1> ;   THE 0 COLOR IS USED.							:
  1928                              <1> ;   ENTRY --									:
  1929                              <1> ;     (AH) = CURRENT CRT MODE							:
  1930                              <1> ;     (AL) = CHARACTER TO BE WRITTEN						:
  1931                              <1> ;	    NOTE THAT BACK SPACE, CARRIAGE RETURN, BELL AND LINE FEED ARE	:
  1932                              <1> ;	    HANDLED AS COMMANDS RATHER THAN AS DISPLAY GRAPHICS CHARACTERS	:
  1933                              <1> ;     (BL) = FOREGROUND COLOR FOR CHAR WRITE IF CURRENTLY IN A GRAPHICS MODE	:
  1934                              <1> ;   EXIT -- 									:
  1935                              <1> ;     ALL REGISTERS SAVED							:
  1936                              <1> ;--------------------------------------------------------------------------------
  1937                              <1> 
  1938 000013C6 FA                  <1> 	cli
  1939                              <1> 	;
  1940                              <1> 	; READ CURSOR (04/12/2013)
  1941                              <1> 	; Retro UNIX 386 v1 Modifications: 30/08/2014
  1942 000013C7 08FF                <1> 	or	bh, bh
  1943                              <1> 	;jnz	beeper
  1944                              <1> 	; 02/02/2022
  1945 000013C9 7405                <1> 	jz	short u14
  1946 000013CB E992000000          <1> 	jmp	beeper
  1947                              <1> u14:
  1948                              <1> 	; 02/02/2022
  1949                              <1> 	;; 01/09/2014
  1950                              <1> 	;cmp	byte [CRT_MODE], 3
  1951                              <1> 	;je	short m3
  1952                              <1> 	;;
  1953                              <1> 	;call	set_mode
  1954                              <1> m3:
  1955 000013D0 89DE                <1> 	mov 	esi, ebx ; 13/08/2015 (0 to 7)
  1956                              <1> 	;shl	si, 1
  1957                              <1> 	; 02/02/2022
  1958 000013D2 D1E6                <1> 	shl	esi, 1
  1959 000013D4 81C6[F66A0000]      <1> 	add	esi, cursor_posn
  1960 000013DA 668B16              <1> 	mov	dx, [esi]
  1961                              <1> 	;
  1962                              <1> 	; dx now has the current cursor position
  1963                              <1> 	;
  1964 000013DD 3C0D                <1> 	cmp	al, 0Dh		; is it carriage return or control character
  1965 000013DF 7647                <1> 	jbe	short u8
  1966                              <1> 	;
  1967                              <1> 	; write the char to the screen
  1968                              <1> u0:	
  1969                              <1> 	; ah = attribute/color
  1970                              <1> 	; al = character
  1971                              <1> 	; bl = video page number (0 to 7)
  1972                              <1> 	; bh = 0
  1973                              <1> 	;
  1974 000013E1 E8D6010000          <1> 	call	write_c_current
  1975                              <1> 	;
  1976                              <1> 	; position the cursor for next char
  1977 000013E6 FEC2                <1> 	inc	dl		; next column
  1978                              <1> 	;cmp	dl, [CRT_COLS]
  1979 000013E8 80FA50              <1> 	cmp	dl, 80		; test for column overflow 
  1980                              <1>         ;jne	set_cpos
  1981                              <1> 	; 02/02/2022
  1982 000013EB 7405                <1> 	je	short u13
  1983 000013ED E9DE000000          <1> 	jmp	set_cpos
  1984                              <1> u13:
  1985 000013F2 B200                <1> 	mov	dl, 0		; column = 0
  1986                              <1> u10:				; (line feed found)
  1987 000013F4 80FE18              <1> 	cmp	dh, 25-1 	; check for last row
  1988 000013F7 7228                <1> 	jb 	short u6
  1989                              <1> 	;
  1990                              <1> 	; scroll required
  1991                              <1> u1:	
  1992                              <1> 	; SET CURSOR POSITION (04/12/2013)
  1993 000013F9 E8D2000000          <1> 	call	set_cpos
  1994                              <1> 	;
  1995                              <1> 	; determine value to fill with during scroll
  1996                              <1> u2:
  1997                              <1> 	; READ_AC_CURRENT		:
  1998                              <1> 	;   THIS ROUTINE READS THE ATTRIBUTE AND CHARACTER
  1999                              <1> 	;    AT THE CURRENT CURSOR POSITION
  2000                              <1> 	;
  2001                              <1> 	; INPUT				
  2002                              <1> 	;	(AH) = CURRENT CRT MODE
  2003                              <1> 	;	(BH) = DISPLAY PAGE ( ALPHA MODES ONLY )
  2004                              <1> 	;	(DS) = DATA SEGMENT
  2005                              <1> 	;	(ES) = REGEN SEGMENT
  2006                              <1> 	; OUTPUT			
  2007                              <1> 	;	(AL) = CHARACTER READ
  2008                              <1> 	;	(AH) = ATTRIBUTE READ
  2009                              <1> 	;
  2010                              <1> 	; mov	ah, [CRT_MODE] ; move current mode into ah
  2011                              <1> 	;
  2012                              <1> 	; bl = video page number
  2013                              <1> 	;
  2014 000013FE E82D010000          <1> 	call	find_position	; get regen location and port address
  2015                              <1> 	; dx = status port
  2016                              <1> 	; esi = cursor location/address
  2017                              <1> p11:
  2018 00001403 FB                  <1> 	sti			; enable interrupts
  2019 00001404 90                  <1> 	nop			; allow for small interupts window
  2020 00001405 FA                  <1> 	cli			; blocks interrupts for single loop
  2021 00001406 EC                  <1> 	in	al, dx		; get status from adapter
  2022 00001407 A801                <1> 	test	al, RHRZ	; is horizontal retrace low
  2023 00001409 75F8                <1> 	jnz	short p11	; wait until it is
  2024                              <1> p12:				; now wait for either retrace high
  2025 0000140B EC                  <1> 	in	al, dx		; get status
  2026 0000140C A809                <1> 	test	al, RVRT+RHRZ	; is horizontal or vertical retrace high
  2027 0000140E 74FB                <1> 	jz	short p12	; wait until either is active	
  2028                              <1> p13:
  2029 00001410 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2030 00001416 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2031                              <1> 	;
  2032                              <1> 	; al = character, ah = attribute
  2033                              <1> 	;
  2034 00001419 FB                  <1> 	sti
  2035                              <1> 	; bl = video page number 	
  2036                              <1> u3:
  2037                              <1> 	;;mov	ax, 0601h 	; scroll one line
  2038                              <1> 	;;sub	cx, cx		; upper left corner
  2039                              <1> 	;;mov	dh, 25-1 	; lower right row
  2040                              <1> 	;;;mov	dl, [CRT_COLS]
  2041                              <1> 	;mov	dl, 80		; lower right column	
  2042                              <1> 	;;dec	dl
  2043                              <1> 	;;mov	dl, 79
  2044                              <1> 
  2045                              <1> 	;;call	scroll_up	; 04/12/2013
  2046                              <1> 	;;; 11/03/2015
  2047                              <1> 	; 02/09/2014
  2048                              <1> 	;;;mov	cx, [crt_ulc] ; Upper left corner  (0000h)
  2049                              <1> 	;;;mov	dx, [crt_lrc] ; Lower right corner (184Fh)
  2050                              <1> 	; 11/03/2015
  2051                              <1> 	;sub	cx, cx
  2052                              <1> 	;mov	dx, 184Fh ; dl= 79 (column), dh = 24 (row)
  2053                              <1> 	;
  2054                              <1> 	; 02/02/2022 (simplied scroll up)
  2055                              <1> 	; ((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2056                              <1> 	;
  2057 0000141A B001                <1> 	mov	al, 1		; scroll 1 line up
  2058                              <1> 		; ah = attribute
  2059 0000141C E939010000          <1> 	jmp	scroll_up
  2060                              <1> ;u4:
  2061                              <1> 	;;int	10h		; video-call return
  2062                              <1> 				; scroll up the screen
  2063                              <1> 				; tty return
  2064                              <1> ;u5:
  2065                              <1> 	;retn			; return to the caller
  2066                              <1> 
  2067                              <1> u6:				; set-cursor-inc
  2068 00001421 FEC6                <1> 	inc	dh		; next row
  2069                              <1> 				; set cursor
  2070                              <1> ;u7:					
  2071                              <1> 	;;mov	ah, 02h
  2072                              <1> 	;;jmp	short u4 	; establish the new cursor
  2073                              <1> 	;call	set_cpos
  2074                              <1> 	;jmp 	short u5
  2075 00001423 E9A8000000          <1> 	jmp     set_cpos
  2076                              <1> 
  2077                              <1> 	; check for control characters
  2078                              <1> u8:
  2079 00001428 7434                <1> 	je	short u9
  2080 0000142A 3C0A                <1> 	cmp	al, 0Ah		; is it a line feed (0Ah)
  2081 0000142C 74C6                <1> 	je	short u10
  2082 0000142E 3C07                <1> 	cmp	al, 07h 	; is it a bell
  2083 00001430 7430                <1> 	je	short u11
  2084 00001432 3C08                <1> 	cmp	al, 08h		; is it a backspace
  2085                              <1> 	;jne	short u0
  2086 00001434 7420                <1> 	je	short bs	; 12/12/2013
  2087                              <1> 	; 12/12/2013 (tab stop)
  2088 00001436 3C09                <1> 	cmp	al, 09h		; is it a tab stop
  2089 00001438 75A7                <1> 	jne	short u0
  2090 0000143A 88D0                <1> 	mov	al, dl
  2091 0000143C 6698                <1> 	cbw
  2092 0000143E B108                <1> 	mov	cl, 8
  2093 00001440 F6F1                <1> 	div	cl
  2094 00001442 28E1                <1> 	sub	cl, ah
  2095                              <1> ts:
  2096                              <1> 	; 02/09/2014
  2097                              <1> 	; 01/09/2014
  2098 00001444 B020                <1> 	mov	al, 20h
  2099                              <1> tsloop:
  2100                              <1> 	;push	cx
  2101                              <1> 	;push	ax
  2102                              <1> 	; 02/02/2022
  2103 00001446 51                  <1> 	push	ecx
  2104 00001447 50                  <1> 	push	eax
  2105 00001448 30FF                <1> 	xor 	bh, bh
  2106                              <1> 	;mov	bl, [active_page]
  2107 0000144A E881FFFFFF          <1> 	call	m3
  2108                              <1> 	; 02/02/2022
  2109 0000144F 58                  <1> 	pop	eax
  2110 00001450 59                  <1>  	pop	ecx
  2111                              <1> 	;pop	ax  ; ah = attribute/color
  2112                              <1> 	;pop	cx
  2113 00001451 FEC9                <1> 	dec	cl
  2114 00001453 75F1                <1> 	jnz	short tsloop
  2115 00001455 C3                  <1> 	retn
  2116                              <1> bs:	
  2117                              <1> 	; back space found
  2118 00001456 08D2                <1> 	or	dl, dl 		; is it already at start of line
  2119                              <1> 	;je	short u7 	; set_cursor
  2120 00001458 7476                <1> 	jz	short set_cpos
  2121                              <1> 	;dec	dx     		; no -- just move it back
  2122                              <1> 	; 02/02/2022
  2123 0000145A FECA                <1> 	dec	dl
  2124                              <1> 	;jmp	short u7
  2125 0000145C EB72                <1> 	jmp	short set_cpos
  2126                              <1> 
  2127                              <1> 	; carriage return found
  2128                              <1> u9:
  2129 0000145E B200                <1> 	mov	dl, 0 		; move to first column
  2130                              <1> 	;jmp	short u7
  2131 00001460 EB6E                <1> 	jmp	short set_cpos
  2132                              <1> 
  2133                              <1> 	; line feed found
  2134                              <1> ;u10:
  2135                              <1> ;	cmp	dh, 25-1 	; bottom of screen
  2136                              <1> ;	jne	short u6 	; no, just set the cursor
  2137                              <1> ;       jmp     u1              ; yes, scroll the screen
  2138                              <1> 
  2139                              <1> beeper: 
  2140                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2141                              <1> 	; 18/01/2014
  2142                              <1> 	; 03/12/2013
  2143                              <1> 	; bell found
  2144                              <1> u11:
  2145 00001462 FB                  <1> 	sti
  2146 00001463 3A1D[066B0000]      <1> 	cmp	bl, [active_page]
  2147 00001469 7551                <1> 	jne	short u12	; Do not sound the beep 
  2148                              <1> 				; if it is not written on the active page
  2149 0000146B 66B93305            <1> 	mov	cx, 1331 	; divisor for 896 hz tone
  2150 0000146F B31F                <1> 	mov	bl, 31		; set count for 31/64 second for beep
  2151                              <1> 	;call	beep		; sound the pod bell
  2152                              <1> 	;jmp	short u5 	; tty_return
  2153                              <1> 	;retn
  2154                              <1> 	
  2155                              <1> TIMER	equ 	040h   		; 8254 TIMER - BASE ADDRESS
  2156                              <1> PORT_B	equ	061h		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2157                              <1> GATE2	equ	00000001b	; TIMER 2 INPUT CATE CLOCK BIT
  2158                              <1> SPK2	equ	00000010b	; SPEAKER OUTPUT DATA ENABLE BIT
  2159                              <1> 
  2160                              <1> beep:
  2161                              <1> 	; 07/02/2015
  2162                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2163                              <1> 	; 18/01/2014
  2164                              <1> 	; 03/12/2013
  2165                              <1> 	;
  2166                              <1> 	; TEST4.ASM - 06/10/85  POST AND BIOS UTILITY ROUTINES
  2167                              <1> 	;
  2168                              <1> 	; ROUTINE TO SOUND THE BEEPER USING TIMER 2 FOR TONE
  2169                              <1> 	;
  2170                              <1> 	; ENTRY:
  2171                              <1> 	;    (BL) = DURATION COUNTER ( 1 FOR 1/64 SECOND )
  2172                              <1> 	;    (CX) = FREQUENCY DIVISOR (1193180/FREQUENCY) (1331 FOR 886 HZ)
  2173                              <1> 	; EXIT:			:
  2174                              <1> 	;    (AX),(BL),(CX) MODIFIED.
  2175                              <1> 
  2176 00001471 9C                  <1> 	pushf  ; 18/01/2014	; save interrupt status
  2177 00001472 FA                  <1> 	cli			; block interrupts during update
  2178 00001473 B0B6                <1> 	mov	al, 10110110b	; select timer 2, lsb, msb binary
  2179 00001475 E643                <1> 	out	TIMER+3, al 	; write timer mode register
  2180 00001477 EB00                <1> 	jmp	$+2		; I/O delay
  2181 00001479 88C8                <1> 	mov	al, cl		; divisor for hz (low)
  2182 0000147B E642                <1> 	out	TIMER+2,AL	; write timer 2 count - lsb
  2183 0000147D EB00                <1> 	jmp	$+2		; I/O delay
  2184 0000147F 88E8                <1> 	mov	al, ch		; divisor for hz (high)
  2185 00001481 E642                <1> 	out	TIMER+2, al	; write timer 2 count - msb
  2186 00001483 E461                <1> 	in	al, PORT_B	; get current setting of port
  2187 00001485 88C4                <1> 	mov	ah, al		; save that setting
  2188 00001487 0C03                <1> 	or	al, GATE2+SPK2	; gate timer 2 and turn speaker on
  2189 00001489 E661                <1> 	out	PORT_B, al	; and restore interrupt status
  2190                              <1> 	;popf	; 18/01/2014
  2191 0000148B FB                  <1> 	sti
  2192                              <1> g7:				; 1/64 second per count (bl)
  2193 0000148C B90B040000          <1> 	mov	ecx, 1035	; delay count for 1/64 of a second	
  2194 00001491 E827000000          <1> 	call	waitf		; go to beep delay 1/64 count
  2195 00001496 FECB                <1> 	dec	bl		; (bl) length count expired?
  2196 00001498 75F2                <1> 	jnz	short g7	; no - continue beeping speaker
  2197                              <1> 	;
  2198                              <1> 	;pushf			; save interrupt status
  2199 0000149A FA                  <1> 	cli  	; 18/01/2014	; block interrupts during update
  2200 0000149B E461                <1> 	in	al, PORT_B	; get current port value
  2201                              <1>         ;or	al, not (GATE2+SPK2) ; isolate current speaker bits in case
  2202 0000149D 0CFC                <1>         or      al, ~(GATE2+SPK2)
  2203 0000149F 20C4                <1>         and	ah, al		; someone turned them off during beep
  2204 000014A1 88E0                <1> 	mov	al, ah		; recover value of port
  2205                              <1>         ;or	al, not (GATE2+SPK2) ; force speaker data off
  2206 000014A3 0CFC                <1> 	or 	al, ~(GATE2+SPK2) ; isolate current speaker bits in case
  2207 000014A5 E661                <1> 	out	PORT_B, al	; and stop speaker timer
  2208                              <1> 	;popf			; restore interrupt flag state
  2209 000014A7 FB                  <1> 	sti
  2210 000014A8 B90B040000          <1> 	mov	ecx, 1035	; force 1/64 second delay (short)
  2211 000014AD E80B000000          <1> 	call	waitf		; minimum delay between all beeps
  2212                              <1> 	;pushf			; save interrupt status
  2213 000014B2 FA                  <1> 	cli			; block interrupts during update
  2214 000014B3 E461                <1> 	in	al, PORT_B	; get current port value in case	
  2215 000014B5 2403                <1> 	and	al, GATE2+SPK2	; someone turned them on
  2216 000014B7 08E0                <1> 	or	al, ah		; recover value of port_b
  2217 000014B9 E661                <1> 	out	PORT_B, al	; restore speaker status
  2218 000014BB 9D                  <1> 	popf			; restore interrupt flag state
  2219                              <1> u12:	
  2220 000014BC C3                  <1> 	retn
  2221                              <1> 
  2222                              <1> REFRESH_BIT equ	00010000b 	; REFRESH TEST BIT
  2223                              <1> 
  2224                              <1> WAITF:
  2225                              <1> waitf:
  2226                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2227                              <1> 	; 03/12/2013
  2228                              <1> 	;
  2229                              <1> ;	push	ax		; save work register (ah)	
  2230                              <1> ;waitf1:
  2231                              <1> 				; use timer 1 output bits
  2232                              <1> ;	in	al, PORT_B	; read current counter output status
  2233                              <1> ;	and	al, REFRESH_BIT	; mask for refresh determine bit
  2234                              <1> ;	cmp	al, ah		; did it just change
  2235                              <1> ;	je	short waitf1	; wait for a change in output line
  2236                              <1> ;	;
  2237                              <1> ;	mov	ah, al		; save new lflag state
  2238                              <1> ;	loop	waitf1		; decrement half cycles till count end		
  2239                              <1> ;	;
  2240                              <1> ;	pop	ax		; restore (ah)
  2241                              <1> ;	retn			; return (cx)=0
  2242                              <1> 
  2243                              <1> ; 02/02/2022
  2244                              <1> ; 06/02/2015 (unix386.s <-- dsectrm2.s)
  2245                              <1> ; 17/12/2014 (dsectrm2.s)
  2246                              <1> ; WAITF
  2247                              <1> ; /// IBM PC-XT Model 286 System BIOS Source Code - Test 4 - 06/10/85 ///
  2248                              <1> ;
  2249                              <1> ;---WAITF-----------------------------------------------------------------------
  2250                              <1> ;	FIXED TIME WAIT ROUTINE (HARDWARE CONTROLLED - NOT PROCESSOR)
  2251                              <1> ; ENTRY:
  2252                              <1> ;	(CX) =	COUNT OF 15.085737 MICROSECOND INTERVALS TO WAIT
  2253                              <1> ;	      	MEMORY REFRESH TIMER 1 OUTPUT USED AS REFERENCE
  2254                              <1> ; EXIT:
  2255                              <1> ;	       	AFTER (CX) TIME COUNT (PLUS OR MINUS 16 MICROSECONDS)
  2256                              <1> ;	(CX) = 0	
  2257                              <1> ;-------------------------------------------------------------------------------
  2258                              <1> 
  2259                              <1> ; Refresh period: 30 micro seconds (15-80 us)
  2260                              <1> ; (16/12/2014 - AWARDBIOS 1999 - ATORGS.ASM, WAIT_REFRESH)
  2261                              <1> 
  2262                              <1> ;WAITF:					; DELAY FOR (CX)*15.085737 US
  2263 000014BD 50                  <1> 	push	eax ; 02/02/2022	; SAVE WORK REGISTER (AH)
  2264                              <1> 	;push	ax
  2265                              <1> 	; 16/12/2014
  2266                              <1> 	;shr	cx, 1			; convert to count of 30 micro seconds
  2267 000014BE D1E9                <1> 	shr	ecx, 1	; 21/02/2015
  2268                              <1> ;17/12/2014	
  2269                              <1> ;WAITF1:
  2270                              <1> ;	IN	AL, PORT_B   ;061h	; READ CURRENT COUNTER OUTPUT STATUS
  2271                              <1> ;	AND	AL, REFRESH_BIT	;00010000b ; MASK FOR REFRESH DETERMINE BIT
  2272                              <1> ;	CMP	AL, AH			; DID IT JUST CHANGE
  2273                              <1> ;	JE	short WAITF1		; WAIT FOR A CHANGE IN OUTPUT LINE
  2274                              <1> ;	MOV	AH, AL			; SAVE NEW FLAG STATE
  2275                              <1> ;	LOOP	WAITF1			; DECREMENT HALF CYCLES TILL COUNT END		
  2276                              <1> 	;
  2277                              <1> 	; 17/12/2014
  2278                              <1> 	;
  2279                              <1> 	; Modification from 'WAIT_REFRESH' procedure of AWARD BIOS - 1999
  2280                              <1> 	;
  2281                              <1> ;WAIT_REFRESH:  Uses port 61, bit 4 to have CPU speed independent waiting.
  2282                              <1> ;   	INPUT:  CX = number of refresh periods to wait
  2283                              <1> ;     	       (refresh periods = 1 per 30 microseconds on most machines)
  2284                              <1> WR_STATE_0:
  2285 000014C0 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2286 000014C2 A810                <1> 	TEST	AL,010H
  2287 000014C4 74FA                <1> 	JZ	SHORT WR_STATE_0
  2288                              <1> WR_STATE_1:
  2289 000014C6 E461                <1> 	IN	AL,PORT_B		; IN AL,SYS1
  2290 000014C8 A810                <1> 	TEST	AL,010H
  2291 000014CA 75FA                <1> 	JNZ	SHORT WR_STATE_1
  2292 000014CC E2F2                <1>         LOOP    WR_STATE_0
  2293                              <1> 	;
  2294                              <1> 	;pop	ax
  2295 000014CE 58                  <1> 	pop	eax ; 02/02/2022	; RESTORE (AH)
  2296 000014CF C3                  <1> 	RETn				; (CX) = 0
  2297                              <1> 
  2298                              <1> set_cpos:
  2299                              <1> 	; 26/02/2022
  2300                              <1> 	; 02/02/2022
  2301                              <1> 	; 27/06/2015
  2302                              <1> 	; 01/09/2014
  2303                              <1> 	; 30/08/2014 (Retro UNIX 386 v1 - beginning)
  2304                              <1> 	;
  2305                              <1> 	; 12/12/2013 (Retro UNIX 8086 v1 - last update) 
  2306                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - beginning)
  2307                              <1> 	;
  2308                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2309                              <1> 	;
  2310                              <1> 	; SET_CPOS
  2311                              <1> 	;	THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE
  2312                              <1> 	;	NEW X-Y VALUES PASSED
  2313                              <1> 	; INPUT
  2314                              <1> 	;	DX - ROW,COLUMN OF NEW CURSOR
  2315                              <1> 	;	BH - DISPLAY PAGE OF CURSOR
  2316                              <1> 	; OUTPUT
  2317                              <1> 	;	CURSOR IS SET AT 6845 IF DISPLAY PAGE IS CURRENT DISPLAY
  2318                              <1> 	;
  2319 000014D0 0FB6C3              <1>         movzx   eax, bl	; BL = video page number ; 27/06/2015 (movzx)
  2320 000014D3 D0E0                <1>         shl     al, 1   ; word offset
  2321 000014D5 BE[F66A0000]        <1> 	mov	esi, cursor_posn
  2322 000014DA 01C6                <1>         add     esi, eax
  2323 000014DC 668916              <1> 	mov	[esi], dx ; save the pointer
  2324 000014DF 381D[066B0000]      <1> 	cmp	[active_page], bl
  2325 000014E5 7536                <1> 	jne	short m17
  2326                              <1> 
  2327 000014E7 FA                  <1> 	cli	; 26/02/2022
  2328                              <1> 
  2329                              <1> 	;call	m18	; CURSOR SET
  2330                              <1> ;m17:			; SET_CPOS_RETURN
  2331                              <1> 	; 01/09/2014
  2332                              <1> ;	retn
  2333                              <1> 		; DX = row/column
  2334                              <1> m18:
  2335 000014E8 E835000000          <1> 	call	position ; determine location in regen buffer	
  2336                              <1> 	;mov	cx, [CRT_START]
  2337                              <1> 	; 26/02/2022
  2338 000014ED 0FB70D[F46A0000]    <1> 	movzx	ecx, word [CRT_START]
  2339 000014F4 01C1                <1> 	add	ecx, eax
  2340                              <1> 	;add	cx, ax  ; add char position in regen buffer
  2341                              <1> 			; to the start address (offset) for this page
  2342                              <1> 	;shr	cx, 1	; divide by 2 for char only count
  2343                              <1> 	; 26/02/2022
  2344 000014F6 D1E9                <1> 	shr	ecx, 1
  2345 000014F8 B40E                <1> 	mov	ah, 14	; register number for cursor
  2346                              <1> 	
  2347 000014FA E802000000          <1> 	call	m16	; output value to the 6845
  2348 000014FF FB                  <1> 	sti	; 26/02/2022
  2349 00001500 C3                  <1> 	retn
  2350                              <1> 
  2351                              <1> 	; 26/02/2022
  2352                              <1> 	; 02/02/2022
  2353                              <1> 	;-----	THIS ROUTINE OUTPUTS THE CX REGISTER
  2354                              <1> 	;	TO THE 6845 REGISTERS NAMED IN (AH)
  2355                              <1> m16:
  2356                              <1> 	;cli	; 26/02/2022
  2357                              <1> 	;mov	dx, [addr_6845] ; address register
  2358 00001501 66BAD403            <1> 	mov 	dx, 03D4h ; I/O address of color card
  2359 00001505 88E0                <1> 	mov	al, ah	; get value
  2360 00001507 EE                  <1> 	out	dx, al	; register set
  2361                              <1> 	;inc	dx	; data register
  2362                              <1> 	; 02/02/2022
  2363 00001508 FEC2                <1> 	inc	dl
  2364 0000150A EB00                <1> 	jmp	$+2	; i/o delay
  2365 0000150C 88E8                <1> 	mov	al, ch	; data
  2366 0000150E EE                  <1> 	out	dx, al	
  2367                              <1> 	;dec	dx
  2368                              <1> 	; 02/02/2022	
  2369 0000150F FECA                <1> 	dec	dl
  2370 00001511 88E0                <1> 	mov	al, ah
  2371 00001513 FEC0                <1> 	inc	al	; point to other data register
  2372 00001515 EE                  <1> 	out	dx, al	; set for second register
  2373                              <1> 	;inc	dx
  2374                              <1> 	; 02/02/2022
  2375 00001516 FEC2                <1> 	inc	dl
  2376 00001518 EB00                <1> 	jmp	$+2	; i/o delay
  2377 0000151A 88C8                <1> 	mov	al, cl	; second data value
  2378 0000151C EE                  <1> 	out	dx, al
  2379                              <1> 	;sti	; 26/02/2022
  2380                              <1> m17:
  2381 0000151D C3                  <1> 	retn
  2382                              <1> 
  2383                              <1> set_ctype:
  2384                              <1> 	; 07/02/2022
  2385                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2386                              <1> 	;
  2387                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2388                              <1> 
  2389                              <1> ;	CH) = BITS 4-0 = START LINE FOR CURSOR
  2390                              <1> ;       ** HARDWARE WILL ALWAYS CAUSE BLINK
  2391                              <1> ;       ** SETTING BIT 5 OR 6 WILL CAUSE ERRATIC BLINKING
  2392                              <1> ;          OR NO CURSOR AT ALL
  2393                              <1> ;	(CL) = BITS 4-0 = END LINE FOR CURSOR
  2394                              <1> 
  2395                              <1> ;------------------------------------------------
  2396                              <1> ; SET_CTYPE
  2397                              <1> ;	THIS ROUTINE SETS THE CURSOR VALUE
  2398                              <1> ; INPUT
  2399                              <1> ;	(CX) HAS CURSOR VALUE CH-START LINE, CL-STOP LINE
  2400                              <1> ; OUTPUT	
  2401                              <1> ;	NONE
  2402                              <1> ;------------------------------------------------
  2403                              <1> 
  2404 0000151E B40A                <1> 	mov	ah, 10	; 6845 register for cursor set
  2405                              <1> 	;mov	[CURSOR_MODE], cx ; save in data area
  2406                              <1> 	;call	m16	; output cx register
  2407                              <1> 	;retn
  2408                              <1> 	; 07/02/2022
  2409 00001520 EBDF                <1> 	jmp	short m16
  2410                              <1> 
  2411                              <1> position:
  2412                              <1> 	; 26/02/2022
  2413                              <1> 	; 02/02/2022
  2414                              <1> 	; 27/06/2015
  2415                              <1> 	; 02/09/2014
  2416                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2417                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1)
  2418                              <1> 	;
  2419                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2420                              <1> 	;
  2421                              <1> 	; POSITION
  2422                              <1> 	;	THIS SERVICE ROUTINE CALCULATES THE REGEN BUFFER ADDRESS
  2423                              <1> 	;	OF A CHARACTER IN THE ALPHA MODE
  2424                              <1> 	; INPUT
  2425                              <1> 	;	AX = ROW, COLUMN POSITION
  2426                              <1> 	; OUTPUT
  2427                              <1> 	;	AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2428                              <1> 
  2429                              <1> 		; DX = ROW, COLUMN POSITION
  2430                              <1> 	;movzx	eax, byte [CRT_COLS] ; 27/06/2015
  2431 00001522 31C0                <1> 	xor	eax, eax ; 02/09/2014
  2432 00001524 B050                <1> 	mov	al, 80	; determine bytes to row	
  2433 00001526 F6E6                <1> 	mul	dh	; row value
  2434                              <1> 	;xor	dh, dh	; 0
  2435                              <1> 	;add	ax, dx	; add column value to the result
  2436                              <1> 	; 26/02/2022
  2437 00001528 00D0                <1> 	add	al, dl
  2438 0000152A 80D400              <1> 	adc	ah, 0	
  2439                              <1> 	;shl	ax, 1	; * 2 for attribute bytes
  2440                              <1> 	; 02/02/2022
  2441 0000152D D1E0                <1> 	shl	eax, 1
  2442                              <1> 		; EAX = AX = OFFSET OF CHAR POSITION IN REGEN BUFFER
  2443 0000152F C3                  <1> 	retn
  2444                              <1> 
  2445                              <1> find_position:
  2446                              <1> 	; 02/02/2022
  2447                              <1> 	; 27/06/2015
  2448                              <1> 	; 07/09/2014
  2449                              <1> 	; 02/09/2014
  2450                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2451                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2452 00001530 0FB6CB              <1> 	movzx	ecx, bl ; video page number ; 27/06/2015 (movzx)
  2453 00001533 89CE                <1> 	mov	esi, ecx
  2454                              <1> 	;shl	si, 1
  2455                              <1> 	; 02/02/2022
  2456 00001535 D1E6                <1> 	shl	esi, 1
  2457 00001537 668B96[F66A0000]    <1> 	mov	dx, [esi+cursor_posn]
  2458 0000153E 7409                <1> 	jz	short p21
  2459                              <1> 	;xor	si, si
  2460                              <1> 	; 02/02/2022
  2461 00001540 31F6                <1> 	xor	esi, esi
  2462                              <1> p20:
  2463                              <1> 	;add	si, [CRT_LEN]
  2464 00001542 6681C6A00F          <1> 	add	si, 80*25*2 ; add length of buffer for one page		
  2465 00001547 E2F9                <1> 	loop	p20
  2466                              <1> p21:
  2467 00001549 6621D2              <1> 	and	dx, dx
  2468 0000154C 7407                <1> 	jz	short p22
  2469 0000154E E8CFFFFFFF          <1> 	call 	position ; determine location in regen in page
  2470 00001553 01C6                <1> 	add	esi, eax ; add location to start of regen page
  2471                              <1> p22:	
  2472                              <1> 	;mov	dx, [addr_6845] ; get base address of active display			
  2473                              <1> 	;mov	dx, 03D4h ; I/O address of color card
  2474                              <1> 	;add	dx, 6	; point at status port
  2475 00001555 66BADA03            <1> 	mov	dx, 03DAh ; status port
  2476                              <1> 	; cx = 0
  2477 00001559 C3                  <1> 	retn
  2478                              <1> 
  2479                              <1> scroll_up:
  2480                              <1> 	; 02/02/2022 (simplified scroll up)
  2481                              <1> 	;	((retro unix 8086 v1 'scroll_up' in 'u9.s'))
  2482                              <1> 	; 16/01/2016
  2483                              <1> 	; 07/09/2014
  2484                              <1> 	; 02/09/2014
  2485                              <1> 	; 01/09/2014 (Retro UNIX 386 v1 - beginning)
  2486                              <1> 	; 04/04/2014
  2487                              <1> 	; 04/12/2013
  2488                              <1> 	;
  2489                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2490                              <1> 	;
  2491                              <1> 	; SCROLL UP
  2492                              <1> 	;	THIS ROUTINE MOVES A BLOCK OF CHARACTERS UP
  2493                              <1> 	;	ON THE SCREEN
  2494                              <1> 	; INPUT
  2495                              <1> 	;	(AH) = CURRENT CRT MODE
  2496                              <1> 	;	(AL) = NUMBER OF ROWS TO SCROLL
  2497                              <1> 	;	(CX) = ROW/COLUMN OF UPPER LEFT CORNER
  2498                              <1> 	;	(DX) = ROW/COLUMN OF LOWER RIGHT CORNER
  2499                              <1> 	;	(BH) = ATTRIBUTE TO BE USED ON BLANKED LINE
  2500                              <1> 	;	(DS) = DATA SEGMENT
  2501                              <1> 	;	(ES) = REGEN BUFFER SEGMENT
  2502                              <1> 	; OUTPUT
  2503                              <1> 	;	NONE -- THE REGEN BUFFER IS MODIFIED
  2504                              <1> 	;
  2505                              <1> 	;	bh = 0  (02/09/2014)
  2506                              <1> 	;
  2507                              <1> 	; ((ah = 3))
  2508                              <1> 	; cl = left upper column
  2509                              <1> 	; ch = left upper row
  2510                              <1> 	; dl = right lower column
  2511                              <1> 	; dh = right lower row
  2512                              <1> 	;
  2513                              <1> 	; al = line count 
  2514                              <1> 	; ah = attribute to be used on blanked line
  2515                              <1> 	; bl = video page number (0 to 7)
  2516                              <1> 	; 
  2517                              <1> 
  2518                              <1> 	; 02/02/2022 'scroll_up' code
  2519                              <1> 	; ------------------------------------------------------
  2520                              <1> 	; (ref: Retro UNIX 8086 v1 'scroll_up' code in 'u9.asm')
  2521                              <1> 
  2522                              <1> 	; INPUT:
  2523                              <1> 	;		
  2524                              <1> 	; al = line count 
  2525                              <1> 	;	(0 or 1) .. 0 -> clear video page
  2526                              <1> 	; ah = attribute to be used on blanked line
  2527                              <1> 	; bl = video page number (0 to 7)
  2528                              <1> 
  2529                              <1> 	;cli
  2530 0000155A 31C9                <1> 	xor	ecx, ecx
  2531 0000155C 88C1                <1> 	mov	cl, al ; line count (cl)
  2532 0000155E BE00800B00          <1> 	mov	esi, 0B8000h
  2533 00001563 3A1D[066B0000]      <1> 	cmp	bl, [active_page]
  2534 00001569 7411                <1> 	je	short n1
  2535 0000156B 20DB                <1> 	and	bl, bl
  2536 0000156D 7422                <1> 	jz	short n3
  2537 0000156F 88DD                <1> 	mov	ch, bl ; video page number
  2538                              <1> n0:
  2539 00001571 6681C6A00F          <1> 	add	si, 25*80*2
  2540 00001576 FECD                <1> 	dec	ch
  2541 00001578 75F7                <1> 	jnz	short n0
  2542 0000157A EB15                <1> 	jmp	short n3
  2543                              <1> n1:
  2544 0000157C 660335[F46A0000]    <1> 	add	si, [CRT_START]
  2545                              <1> 	;
  2546 00001583 66BADA03            <1> 	mov	dx, 3DAh ; guaranteed to be color card here	
  2547                              <1> n2:			 ; wait_display_enable
  2548 00001587 EC                  <1> 	in	al, dx	 ; get port
  2549 00001588 A808                <1> 	test	al, RVRT ; wait for vertical retrace	
  2550 0000158A 74FB                <1> 	jz	short n2 ; wait_display_enable
  2551 0000158C B025                <1> 	mov	al, 25h
  2552 0000158E B2D8                <1> 	mov	dl, 0D8h ; address control port
  2553 00001590 EE                  <1> 	out	dx, al	 ; turn off video during vertical retrace
  2554                              <1> n3:
  2555                              <1> 	; cl = line count
  2556                              <1> 	; ah = attribute/color
  2557 00001591 89F7                <1> 	mov	edi, esi
  2558 00001593 20C9                <1> 	and	cl, cl
  2559 00001595 741F                <1> 	jz	short n6
  2560 00001597 6681C6A000          <1> 	add	si, 80*2 ; + 160 bytes
  2561 0000159C 66B98007            <1> 	mov	cx, 24*80 ; 24 rows/lines
  2562 000015A0 F366A5              <1> 	rep	movsw
  2563 000015A3 B150                <1> 	mov	cl, 80 ; 1 row (will be cleared)
  2564                              <1> n4:
  2565                              <1> 	; ah = character attribute/cocor
  2566 000015A5 B020                <1> 	mov	al, 20h ; fill with blanks
  2567 000015A7 F366AB              <1> 	rep	stosw
  2568                              <1> 
  2569 000015AA 3A1D[066B0000]      <1> 	cmp	bl, [active_page]
  2570 000015B0 7503                <1> 	jne	short n5
  2571                              <1> 
  2572                              <1> 	;mov	al, [crt_mode_set] ; get the value of mode set
  2573 000015B2 B029                <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3	
  2574                              <1> 	;mov	dx, 03D8h ; always set color card port
  2575 000015B4 EE                  <1> 	out	dx, al
  2576                              <1> n5:
  2577 000015B5 C3                  <1> 	retn
  2578                              <1> n6:
  2579                              <1> 	; clear video page
  2580 000015B6 66B9D007            <1> 	mov	cx, 25*80 ; 25 rows/lines
  2581 000015BA EBE9                <1> 	jmp	short n4
  2582                              <1> 
  2583                              <1> 	; 26/02/2022
  2584                              <1> %if 0	; 16/01/2016 'scroll_up' code
  2585                              <1> 	; ------------------------------------------------------
  2586                              <1> 
  2587                              <1> 	; Test	Line Count
  2588                              <1> 	or	al, al
  2589                              <1> 	jz	short al_set
  2590                              <1> 	mov	bh, dh	; subtract lower row from upper row
  2591                              <1> 	sub	bh, ch
  2592                              <1> 	inc	bh	; adjust difference by 1
  2593                              <1> 	cmp	bh, al 	; line count = amount of rows in window?
  2594                              <1> 	jne	short al_set ; if not the we're all set
  2595                              <1> 	xor	al, al	; otherwise set al to zero
  2596                              <1> al_set:
  2597                              <1> 	xor	bh, bh	; 0
  2598                              <1> 	;push	ax
  2599                              <1> 	push	eax ; 26/02/2022
  2600                              <1> 	;mov 	esi, [crt_base]
  2601                              <1>         mov     esi, 0B8000h  
  2602                              <1>         cmp     bl, [active_page]
  2603                              <1> 	jne	short n0
  2604                              <1> 	;
  2605                              <1>         mov     ax, [CRT_START]
  2606                              <1>         add     si, ax
  2607                              <1>         jmp     short n1
  2608                              <1> n0:
  2609                              <1>         and     bl, bl
  2610                              <1> 	jz	short n1
  2611                              <1> 	mov	al, bl
  2612                              <1> n0x:
  2613                              <1>         ;add    si, [CRT_LEN]
  2614                              <1>         ;add    esi, 80*25*2 
  2615                              <1>         add     si, 80*25*2
  2616                              <1>         dec	al
  2617                              <1> 	jnz	short n0x
  2618                              <1> n1:	
  2619                              <1>         ; Scroll position
  2620                              <1> 	;push	dx ; 26/02/2022
  2621                              <1> 	mov	dx, cx	; now, upper left position in DX
  2622                              <1> 	call	position
  2623                              <1> 	add	esi, eax
  2624                              <1> 	mov	edi, esi
  2625                              <1> 	;pop	dx	; lower right position in DX
  2626                              <1> 	sub	dx, cx
  2627                              <1> 	inc	dh	; dh = #rows 
  2628                              <1> 	inc	dl	; dl = #cols in block
  2629                              <1> 	;pop	ax	; al = line count, ah = attribute
  2630                              <1> 	pop	eax ; 26/02/2022
  2631                              <1> 	xor	ecx, ecx
  2632                              <1> 	mov	cx, ax
  2633                              <1> 	;mov	ah, [CRT_COLS]
  2634                              <1> 	mov	ah, 80
  2635                              <1> 	mul	ah	; determine offset to from address
  2636                              <1> 	add	ax, ax  ; *2 for attribute byte
  2637                              <1> 	;
  2638                              <1> 	;push	ax	; offset 
  2639                              <1> 	;push	dx
  2640                              <1> 	; 26/02/2022
  2641                              <1> 	push	eax
  2642                              <1> 	push	edx
  2643                              <1> 	;
  2644                              <1> 	; 04/04/2014
  2645                              <1> 	mov	dx, 3DAh ; guaranteed to be color card here
  2646                              <1> n8:                      ; wait_display_enable
  2647                              <1>         in      al, dx   ; get port
  2648                              <1> 	test	al, RVRT ; wait for vertical retrace
  2649                              <1> 	jz	short n8 ; wait_display_enable
  2650                              <1> 	mov	al, 25h
  2651                              <1> 	mov	dl, 0D8h ; address control port
  2652                              <1> 	out	dx, al	; turn off video during vertical retrace
  2653                              <1> 	;pop	dx	; #rows, #cols
  2654                              <1>        	;pop	ax	; offset
  2655                              <1> 	; 26/02/2022
  2656                              <1> 	pop	edx
  2657                              <1> 	pop	eax
  2658                              <1> 	xchg	ax, cx	; 
  2659                              <1> 	; ecx = offset, al = line count, ah = attribute
  2660                              <1> ;n9:
  2661                              <1> 	or	al, al
  2662                              <1>         jz      short n3 
  2663                              <1>         add     esi, ecx ; from address for scroll
  2664                              <1> 	mov	bh, dh  ; #rows in block
  2665                              <1> 	sub	bh, al	; #rows to be moved
  2666                              <1> n2:
  2667                              <1> 	; Move rows
  2668                              <1> 	mov	cl, dl	; get # of cols to move
  2669                              <1> 	push	esi
  2670                              <1> 	push	edi	; save start address
  2671                              <1> n10:
  2672                              <1> 	movsw		; move that line on screen
  2673                              <1> 	dec	cl
  2674                              <1>         jnz     short n10
  2675                              <1> 	pop	edi
  2676                              <1> 	pop	esi	; recover addresses
  2677                              <1>         ;mov    cl, [CRT_COLS] 
  2678                              <1> 	;add	cl, cl
  2679                              <1>         ;mov    ecx, 80*2
  2680                              <1>         mov     cx, 80*2
  2681                              <1>         add     esi, ecx  ; next line
  2682                              <1>         add     edi, ecx
  2683                              <1> 	dec	bh	 ; count of lines to move
  2684                              <1> 	jnz	short n2 ; row loop
  2685                              <1> 	; bh = 0
  2686                              <1> 	mov	dh, al	 ; #rows	
  2687                              <1> n3:
  2688                              <1> 	; attribute in ah
  2689                              <1> 	mov	al, ' '	 ; fill with blanks
  2690                              <1> n3x:
  2691                              <1> 	; Clear rows
  2692                              <1>                 ; dh =  #rows
  2693                              <1>         mov	cl, dl	; get # of cols to clear
  2694                              <1>         push    edi     ; save address
  2695                              <1> n11:
  2696                              <1>         stosw           ; store fill character
  2697                              <1> 	dec	cl
  2698                              <1>         jnz     short n11
  2699                              <1>         pop     edi     ; recover address
  2700                              <1> 	;mov	cl, [CRT_COLS]
  2701                              <1> 	;add	cl, cl
  2702                              <1>         ;mov    ecx, 80*2
  2703                              <1>         mov	cl, 80*2
  2704                              <1>         add     edi, ecx
  2705                              <1> 	dec	dh
  2706                              <1> 	jnz	short n3x ; 16/01/2016
  2707                              <1> 	;
  2708                              <1> 	cmp	bl, [active_page]
  2709                              <1> 	jne	short n6
  2710                              <1> 	;mov	al, [CRT_MODE_SET] ; get the value of mode set
  2711                              <1> 	mov	al, 29h ; (ORGS.ASM), M7 mode set table value for mode 3
  2712                              <1> 	mov	dx, 03D8h ; always set color card port
  2713                              <1> 	out	dx, al
  2714                              <1> n6:
  2715                              <1> 	retn
  2716                              <1> 
  2717                              <1> %endif
  2718                              <1> 
  2719                              <1> write_c_current:
  2720                              <1> 	; 02/02/2022
  2721                              <1> 	; 30/08/2014 (Retro UNIX 386 v1)
  2722                              <1> 	; 18/01/2014
  2723                              <1> 	; 04/12/2013
  2724                              <1> 	;
  2725                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2726                              <1> 	;
  2727                              <1> 	; WRITE_C_CURRENT
  2728                              <1> 	;	THIS ROUTINE WRITES THE CHARACTER AT
  2729                              <1> 	;	THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED
  2730                              <1> 	; INPUT	
  2731                              <1> 	;	(AH) = CURRENT CRT MODE
  2732                              <1> 	;	(BH) = DISPLAY PAGE
  2733                              <1> 	;	(CX) = COUNT OF CHARACTERS TO WRITE
  2734                              <1> 	;	(AL) = CHAR TO WRITE
  2735                              <1> 	;	(DS) = DATA SEGMENT
  2736                              <1> 	;	(ES) = REGEN SEGMENT
  2737                              <1> 	; OUTPUT
  2738                              <1> 	;	DISPLAY REGEN BUFFER UPDATED
  2739                              <1> 
  2740 000015BC FA                  <1> 	cli		
  2741                              <1> 	; bl = video page
  2742                              <1> 	; al = character
  2743                              <1> 	; ah = color/attribute
  2744                              <1> 	;push	dx
  2745                              <1> 	;push	ax	; save character & attribute/color
  2746                              <1> 	; 02/02/2022
  2747 000015BD 52                  <1> 	push	edx
  2748 000015BE 50                  <1> 	push	eax
  2749 000015BF E86CFFFFFF          <1> 	call 	find_position  ; get regen location and port address
  2750                              <1> 	; esi = regen location
  2751                              <1> 	; dx = status port
  2752                              <1> 	;
  2753                              <1> 	; WAIT FOR HORIZONTAL RETRACE OR VERTICAL RETRACE
  2754                              <1> 	;
  2755                              <1> p41:			; wait for horizontal retrace is low or vertical
  2756 000015C4 FB                  <1> 	sti		; enable interrupts first
  2757 000015C5 3A1D[066B0000]      <1>         cmp     bl, [active_page]
  2758 000015CB 7510                <1> 	jne	short p44 
  2759 000015CD FA                  <1> 	cli 		; block interrupts for single loop
  2760 000015CE EC                  <1> 	in	al, dx	; get status from the adapter
  2761 000015CF A808                <1> 	test	al, RVRT ; check for vertical retrace first
  2762 000015D1 7509                <1> 	jnz	short p43 ; Do fast write now if vertical retrace
  2763 000015D3 A801                <1> 	test	al, RHRZ  ; is horizontal retrace low
  2764 000015D5 75ED                <1> 	jnz	short p41 ; wait until it is
  2765                              <1> p42:			; wait for either retrace high
  2766 000015D7 EC                  <1> 	in	al, dx	; get status again
  2767 000015D8 A809                <1> 	test	al, RVRT+RHRZ ; is horizontal or vertical retrace high
  2768 000015DA 74FB                <1> 	jz	short p42 ; wait until either retrace active
  2769                              <1> p43:	
  2770 000015DC FB                  <1> 	sti
  2771                              <1> p44:
  2772                              <1> 	;pop	ax	; restore the character (al) & attribute (ah)
  2773                              <1> 	; 02/02/2022
  2774 000015DD 58                  <1> 	pop	eax
  2775 000015DE 81C600800B00        <1> 	add	esi, 0B8000h ; 30/08/2014 (crt_base) 
  2776                              <1> 			; Retro UNIX 386 v1 feature only!
  2777 000015E4 668906              <1> 	mov	[esi], ax
  2778                              <1> 	;pop	dx
  2779                              <1> 	; 02/02/2022
  2780 000015E7 5A                  <1> 	pop	edx
  2781 000015E8 C3                  <1> 	retn
  2782                              <1> 
  2783                              <1> %if 0	; 02/02/2022
  2784                              <1> 
  2785                              <1> set_mode:
  2786                              <1> 	; 02/02/2022
  2787                              <1> 	; 16/01/2016
  2788                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2789                              <1> 	;
  2790                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2791                              <1> 
  2792                              <1> ;------------------------------------------------------
  2793                              <1> ; SET MODE					      :
  2794                              <1> ;	THIS ROUTINE INITIALIZES THE ATTACHMENT TO    :
  2795                              <1> ;	THE SELECTED MODE, THE SCREEN IS BLANKED.     :
  2796                              <1> ; INPUT						      :
  2797                              <1> ;	(AL) - MODE SELECTED (RANGE 0-7)	      :
  2798                              <1> ; OUTPUT					      :
  2799                              <1> ;	NONE					      :
  2800                              <1> ;------------------------------------------------------
  2801                              <1> 
  2802                              <1> 	push	edi ; 16/01/2016
  2803                              <1> 	push	ebx
  2804                              <1> 	push	edx
  2805                              <1> 	push	ecx ; 16/01/2016
  2806                              <1>         push    eax
  2807                              <1> 
  2808                              <1> 	;mov	dx, 03D4h 	; address or color card
  2809                              <1> 	mov	al, 3
  2810                              <1> ;M8:
  2811                              <1> 	mov	[CRT_MODE], al  ; save mode in global variable
  2812                              <1> 	mov	al, 29h
  2813                              <1> 	;mov	[CRT_MODE_SET], al ; save the mode set value
  2814                              <1> 	and	al, 037h	; video off, save high resolution bit	
  2815                              <1> 	;push	dx  		; save port value
  2816                              <1> 	;add	dx, 4		; point to control register
  2817                              <1> 	mov	dx, 3D8h
  2818                              <1> 	out	dx, al		; reset video to off to suppress rolling
  2819                              <1> 	;pop	dx
  2820                              <1> ;M9:
  2821                              <1> 	mov	ebx, video_params ; initialization table
  2822                              <1> 	;mov	ax, [ebx+10]      ; get the cursor mode from the table	
  2823                              <1> 	;xchg 	ah, al
  2824                              <1> 	;mov	[CURSOR_MODE], ax ; save cursor mode
  2825                              <1> 	xor	ah, ah		  ; ah is register number during loop 
  2826                              <1> 	
  2827                              <1> ;-----	LOOP THROUGH TABLE, OUTPUTTING REGISTER ADDRESS, THEN VALUE FROM TABLE
  2828                              <1> 	; 02/02/2022
  2829                              <1> 	; dx = 3D8h
  2830                              <1> 	xor	ecx, ecx
  2831                              <1> 	mov	cl, 16
  2832                              <1> 	;mov	ecx, 16 ; 16/01/2016
  2833                              <1> M10:			;  initialization loop
  2834                              <1> 	mov	al, ah 	; get 6845 register number
  2835                              <1> 	out	dx, al
  2836                              <1> 	;inc	dx      ; point to data port
  2837                              <1> 	; 02/02/2022
  2838                              <1> 	inc	dl ; 3D9h
  2839                              <1> 	inc	ah	; next register value
  2840                              <1> 	mov	al, [ebx] ; get table value
  2841                              <1> 	out	dx, al	; out to chip
  2842                              <1> 	inc	ebx	; next in table
  2843                              <1> 	;dec	dx	; back to pointer register
  2844                              <1> 	; 02/02/2022
  2845                              <1> 	dec	dl ; 3D8h
  2846                              <1> 	loop	M10	; do the whole table
  2847                              <1> 	
  2848                              <1> ;-----	FILL REGEN AREA WITH BLANK
  2849                              <1> 	;xor	ax, ax  
  2850                              <1> 	;mov	[CRT_START], ax  ; start address saved in global
  2851                              <1> 	;mov	[ACTIVE_PAGE], al ; 0 ; (re)set page value
  2852                              <1> 	;mov	ecx, 8192 ; number of words in color card
  2853                              <1> 	; black background, light gray characeter color, space character
  2854                              <1> 	;mov	ax, 0720h ; fill char for alpha - attribute
  2855                              <1> ;M13:			  ; clear buffer
  2856                              <1> 	;add	edi, 0B8000h ; [crt_base]
  2857                              <1> 	;rep	stosw	; FILL THE REGEN BUFFER WITH BLANKS
  2858                              <1> 
  2859                              <1> ;-----	ENABLE VIDEO AND CORRECT PORT SETTING
  2860                              <1> 	;mov	dx, 3D4h ; mov dx, word [ADDR_6845]
  2861                              <1> 			 ; prepare to output to video enable port
  2862                              <1> 	;;add	dx, 4	 ; point to the mode control gerister
  2863                              <1> 	; 02/02/2022
  2864                              <1> 	;mov	dx, 3D8h
  2865                              <1> 	; 
  2866                              <1> 	;mov	al, [CRT_MODE_SET] ; get the mode set value
  2867                              <1> 	mov	al, 29h
  2868                              <1> 	out	dx, al	 ; set video enable port
  2869                              <1> 
  2870                              <1> ;----- 	DETERMINE NUMBER OF COLUMNS, BOTH FOR ENTIRE DISPLAY
  2871                              <1> ;----- 	AND THE NUMBER TO BE USED FOR TTY INTERFACE
  2872                              <1> 	;
  2873                              <1> 	;mov byte [CRT_COLS], 80h ; initialize number of columns count
  2874                              <1> 	;
  2875                              <1> ;-----	SET CURSOR POSITIONS
  2876                              <1> 	;push	edi
  2877                              <1> 	;mov	word [CRT_LEN], 80*25*2
  2878                              <1> 	mov	edi, cursor_posn
  2879                              <1> 	mov	ecx, 4	; clear all cursor positions (16 bytes)
  2880                              <1> 	xor	eax, eax
  2881                              <1> 	rep 	stosd	; fill with zeroes
  2882                              <1> 	;pop	edi
  2883                              <1> 
  2884                              <1> ;-----	SET UP OVERSCAN REGISTER
  2885                              <1> 	inc	dx	; set overscan port to a default
  2886                              <1> 	mov	al, 30h	; 30H valuye for all modes except 640X200 bw
  2887                              <1> ;M14:
  2888                              <1> 	out	dx, al	; output the correct value to 3D9 port
  2889                              <1> 	;mov	[CRT_PALETTE], al ; save the value for future use
  2890                              <1> 
  2891                              <1> ;-----	NORMAL RETURN FROM ALL VIDEO RETURNS
  2892                              <1> 	;
  2893                              <1> 	pop	eax
  2894                              <1> 	pop	ecx ; 16/01/2016
  2895                              <1> 	pop	edx
  2896                              <1> 	pop	ebx
  2897                              <1> 	pop	edi ; 16/01/2016
  2898                              <1> 	retn
  2899                              <1> 
  2900                              <1> %endif
  2901                              <1> 	
  2902                              <1> tty_sw:
  2903                              <1> 	; 02/02/2022
  2904                              <1> 	; 30/06/2015
  2905                              <1> 	; 27/06/2015 
  2906                              <1> 	; 07/09/2014
  2907                              <1> 	; 02/09/2014 (Retro UNIX 386 v1 - beginning)
  2908                              <1> 	;
  2909                              <1> 	; (Modified registers : EAX)
  2910                              <1> 	;
  2911                              <1>         ;mov     byte [u.quant], 0  ; 04/03/2014
  2912                              <1> 	;
  2913                              <1> ;act_disp_page:
  2914                              <1> 	; 30/06/2015
  2915                              <1> 	; 04/03/2014  (act_disp_page --> tty_sw)
  2916                              <1> 	; 10/12/2013
  2917                              <1> 	; 04/12/2013
  2918                              <1> 	;
  2919                              <1> 	; VIDEO.ASM - 06/10/85  VIDEO DISPLAY BIOS
  2920                              <1> 	;
  2921                              <1> 	; ACT_DISP_PAGE
  2922                              <1> 	;	THIS ROUTINE SETS THE ACTIVE DISPLAY PAGE, ALLOWING
  2923                              <1> 	;	THE FULL USE OF THE MEMORY SET ASIDE FOR THE VIDEO ATTACHMENT
  2924                              <1> 	; INPUT
  2925                              <1> 	;	AL HAS THE NEW ACTIVE DISPLAY PAGE
  2926                              <1> 	; OUTPUT
  2927                              <1> 	;	THE 6845 IS RESET TO DISPLAY THAT PAGE
  2928                              <1> 
  2929                              <1> 	;cli
  2930                              <1> 
  2931 000015E9 53                  <1> 	push	ebx
  2932                              <1> 	;push	cx
  2933                              <1> 	;push	dx
  2934                              <1> 	; 02/02/2022
  2935 000015EA 51                  <1> 	push	ecx
  2936 000015EB 52                  <1> 	push	edx
  2937                              <1> 	;
  2938 000015EC A2[066B0000]        <1> 	mov	[active_page], al ; save active page value ; [ptty]
  2939                              <1> 	;;mov	cx, [CRT_LEN] ; get saved length of regen buffer
  2940                              <1> 	;mov	cx, 25*80*2
  2941                              <1> 	; 02/02/2022
  2942 000015F1 B9A00F0000          <1> 	mov	ecx, 25*80*2
  2943                              <1> 	; 27/06/2015
  2944 000015F6 0FB6D8              <1> 	movzx	ebx, al
  2945                              <1> 	; 02/02/2022
  2946 000015F9 89D8                <1> 	mov	eax, ebx
  2947                              <1> 	;
  2948                              <1> 	;cbw	; 07/09/2014 (ah=0)
  2949                              <1> 	;mul 	cx	; display page times regen length
  2950                              <1> 	; 02/02/2022
  2951 000015FB F7E1                <1> 	mul	ecx	
  2952                              <1> 	; 10/12/2013
  2953 000015FD 66A3[F46A0000]      <1> 	mov	[CRT_START], ax ; save start address for later
  2954                              <1> 	;mov	cx, ax	; start address to cx
  2955                              <1> 	; 02/02/2022
  2956 00001603 89C1                <1> 	mov	ecx, eax
  2957                              <1> 	;sar	cx, 1
  2958                              <1> 	;shr	cx, 1	; divide by 2 for 6845 handling
  2959                              <1> 	; 02/02/2022
  2960 00001605 D1E9                <1> 	shr	ecx, 1
  2961 00001607 B40C                <1> 	mov	ah, 12	; 6845 register for start address
  2962 00001609 E8F3FEFFFF          <1> 	call	m16
  2963                              <1> 	;sal	bx, 1
  2964                              <1> 	; 01/09/2014
  2965 0000160E D0E3                <1> 	shl	bl, 1	; * 2 for word offset
  2966 00001610 81C3[F66A0000]      <1> 	add	ebx, cursor_posn
  2967 00001616 668B13              <1> 	mov	dx, [ebx] ; get cursor for this page
  2968 00001619 E8CAFEFFFF          <1> 	call	m18
  2969                              <1> 	;
  2970                              <1> 	;pop	dx
  2971                              <1> 	;pop	cx
  2972                              <1> 	; 02/02/2022
  2973 0000161E 5A                  <1> 	pop	edx
  2974 0000161F 59                  <1> 	pop	ecx
  2975 00001620 5B                  <1> 	pop	ebx
  2976                              <1> 	;
  2977                              <1> 	;sti
  2978                              <1> 	;
  2979 00001621 C3                  <1> 	retn
  2980                              <1> 
  2981                              <1> ; %include 'vidata.inc' ; VIDEO DATA ; 11/03/2015
  2982                              <1> 
  2983                              <1> ; /// End Of VIDEO FUNCTIONS ///
  1876                                  
  1877                                  setup_rtc_int:
  1878                                  ; source: http://wiki.osdev.org/RTC
  1879 00001622 FA                      	cli		; disable interrupts
  1880                                  	; default int frequency is 1024 Hz (Lower 4 bits of register A is 0110b or 6)
  1881                                  	; in order to change this ...
  1882                                  	; frequency  = 32768 >> (rate-1) --> 32768 >> 5 = 1024
  1883                                  	; (rate must be above 2 and not over 15)
  1884                                  	; new rate = 15 --> 32768 >> (15-1) = 2 Hz
  1885 00001623 B08A                    	mov	al, 8Ah 
  1886 00001625 E670                    	out	70h, al ; set index to register A, disable NMI
  1887 00001627 90                      	nop
  1888 00001628 E471                    	in	al, 71h ; get initial value of register A
  1889 0000162A 88C4                    	mov 	ah, al
  1890 0000162C 80E4F0                  	and	ah, 0F0h
  1891 0000162F B08A                    	mov	al, 8Ah 
  1892 00001631 E670                    	out	70h, al ; reset index to register A
  1893 00001633 88E0                    	mov	al, ah
  1894 00001635 0C0F                    	or	al, 0Fh	; new rate (0Fh -> 15)
  1895 00001637 E671                    	out	71h, al ; write only our rate to A. Note, rate is the bottom 4 bits. 
  1896                                  	; enable RTC interrupt
  1897 00001639 B08B                    	mov	al, 8Bh ;
  1898 0000163B E670                    	out	70h, al ; select register B and disable NMI
  1899 0000163D 90                      	nop
  1900 0000163E E471                    	in	al, 71h ; read the current value of register B
  1901 00001640 88C4                    	mov	ah, al  ;
  1902 00001642 B08B                    	mov 	al, 8Bh ;
  1903 00001644 E670                    	out	70h, al ; set the index again (a read will reset the index to register B)	
  1904 00001646 88E0                    	mov	al, ah  ;
  1905 00001648 0C40                    	or	al, 40h ;
  1906 0000164A E671                    	out	71h, al ; write the previous value ORed with 0x40. This turns on bit 6 of register B
  1907 0000164C FB                      	sti
  1908 0000164D C3                      	retn
  1909                                  
  1910                                  ; Write memory information
  1911                                  ; Temporary Code
  1912                                  ; 06/11/2014
  1913                                  ; 14/08/2015 
  1914                                  memory_info:	
  1915 0000164E A1[DC6A0000]            	mov	eax, [memory_size] ; in pages
  1916 00001653 50                      	push	eax
  1917 00001654 C1E00C                  	shl	eax, 12		   ; in bytes
  1918 00001657 BB0A000000              	mov	ebx, 10
  1919 0000165C 89D9                    	mov	ecx, ebx	   ; 10
  1920 0000165E BE[41670000]            	mov	esi, mem_total_b_str	
  1921 00001663 E8AE000000              	call	bintdstr
  1922 00001668 58                      	pop	eax
  1923 00001669 B107                    	mov	cl, 7
  1924 0000166B BE[65670000]            	mov	esi, mem_total_p_str
  1925 00001670 E8A1000000              	call	bintdstr	
  1926                                  	; 14/08/2015
  1927 00001675 E8B9000000              	call	calc_free_mem
  1928                                  	; edx = calculated free pages
  1929                                  	; ecx = 0
  1930 0000167A A1[E06A0000]            	mov 	eax, [free_pages]
  1931 0000167F 39D0                    	cmp	eax, edx ; calculated free mem value 
  1932                                  		; and initial free mem value are same or not?
  1933 00001681 751D                    	jne 	short pmim ; print mem info with '?' if not
  1934 00001683 52                      	push 	edx ; free memory in pages	
  1935                                  	;mov 	eax, edx
  1936 00001684 C1E00C                  	shl	eax, 12 ; convert page count
  1937                                  			; to byte count
  1938 00001687 B10A                    	mov	cl, 10
  1939 00001689 BE[85670000]            	mov	esi, free_mem_b_str
  1940 0000168E E883000000              	call	bintdstr
  1941 00001693 58                      	pop	eax
  1942 00001694 B107                    	mov	cl, 7
  1943 00001696 BE[A9670000]            	mov	esi, free_mem_p_str
  1944 0000169B E876000000              	call	bintdstr
  1945                                  pmim:
  1946 000016A0 BE[2F670000]            	mov	esi, msg_memory_info
  1947                                  pmim_nb:	
  1948 000016A5 AC                      	lodsb
  1949 000016A6 08C0                    	or	al, al
  1950 000016A8 740D                    	jz	short pmim_ok
  1951 000016AA 56                      	push	esi
  1952 000016AB 31DB                    	xor	ebx, ebx ; 0
  1953                                  			; Video page 0 (bl=0)
  1954 000016AD B407                    	mov	ah, 07h ; Black background, 
  1955                                  			; light gray forecolor
  1956 000016AF E812FDFFFF              	call	write_tty
  1957 000016B4 5E                      	pop	esi
  1958 000016B5 EBEE                    	jmp	short pmim_nb
  1959                                  pmim_ok:
  1960 000016B7 C3                      	retn
  1961                                  
  1962                                  ; Convert binary number to hexadecimal string
  1963                                  ; 10/05/2015  
  1964                                  ; dsectpm.s (28/02/2015)
  1965                                  ; Retro UNIX 386 v1 - Kernel v0.2.0.6  
  1966                                  ; 01/12/2014
  1967                                  ; 25/11/2014
  1968                                  ;
  1969                                  bytetohex:
  1970                                  	; INPUT ->
  1971                                  	; 	AL = byte (binary number)
  1972                                  	; OUTPUT ->
  1973                                  	;	AX = hexadecimal string
  1974                                  	;
  1975 000016B8 53                      	push	ebx
  1976 000016B9 31DB                    	xor	ebx, ebx
  1977 000016BB 88C3                    	mov	bl, al
  1978 000016BD C0EB04                  	shr	bl, 4
  1979 000016C0 8A9B[06170000]          	mov	bl, [ebx+hexchrs]
  1980 000016C6 86D8                    	xchg	bl, al
  1981 000016C8 80E30F                  	and	bl, 0Fh
  1982 000016CB 8AA3[06170000]          	mov	ah, [ebx+hexchrs]
  1983 000016D1 5B                      	pop	ebx	
  1984 000016D2 C3                      	retn
  1985                                  
  1986                                  wordtohex:
  1987                                  	; INPUT ->
  1988                                  	; 	AX = word (binary number)
  1989                                  	; OUTPUT ->
  1990                                  	;	EAX = hexadecimal string
  1991                                  	;
  1992 000016D3 53                      	push	ebx
  1993 000016D4 31DB                    	xor	ebx, ebx
  1994 000016D6 86E0                    	xchg	ah, al
  1995 000016D8 6650                    	push	ax
  1996 000016DA 88E3                    	mov	bl, ah
  1997 000016DC C0EB04                  	shr	bl, 4
  1998 000016DF 8A83[06170000]          	mov	al, [ebx+hexchrs]
  1999 000016E5 88E3                    	mov	bl, ah
  2000 000016E7 80E30F                  	and	bl, 0Fh
  2001 000016EA 8AA3[06170000]          	mov	ah, [ebx+hexchrs]
  2002 000016F0 C1E010                  	shl	eax, 16
  2003 000016F3 6658                    	pop	ax
  2004 000016F5 5B                      	pop	ebx
  2005 000016F6 EBC0                    	jmp	short bytetohex
  2006                                  	;mov	bl, al
  2007                                  	;shr	bl, 4
  2008                                  	;mov	bl, [ebx+hexchrs]
  2009                                  	;xchg	bl, al	 	
  2010                                  	;and	bl, 0Fh
  2011                                  	;mov	ah, [ebx+hexchrs]
  2012                                  	;pop	ebx	
  2013                                  	;retn
  2014                                  
  2015                                  dwordtohex:
  2016                                  	; INPUT ->
  2017                                  	; 	EAX = dword (binary number)
  2018                                  	; OUTPUT ->
  2019                                  	;	EDX:EAX = hexadecimal string
  2020                                  	;
  2021 000016F8 50                      	push	eax
  2022 000016F9 C1E810                  	shr	eax, 16
  2023 000016FC E8D2FFFFFF              	call	wordtohex
  2024 00001701 89C2                    	mov	edx, eax
  2025 00001703 58                      	pop	eax
  2026                                  	;call	wordtohex
  2027                                  	;retn
  2028                                  	; 02/01/2022
  2029 00001704 EBCD                    	jmp	short wordtohex
  2030                                  
  2031                                  ; 10/05/2015
  2032                                  hex_digits:
  2033                                  hexchrs:
  2034 00001706 303132333435363738-     	db '0123456789ABCDEF'
  2034 0000170F 39414243444546     
  2035                                  
  2036                                  ; Convert binary number to decimal/numeric string
  2037                                  ; 06/11/2014
  2038                                  ; Temporary Code
  2039                                  ;
  2040                                  
  2041                                  bintdstr:
  2042                                  	; EAX = binary number
  2043                                  	; ESI = decimal/numeric string address
  2044                                  	; EBX = divisor (10)
  2045                                  	; ECX = string length (<=10)
  2046 00001716 01CE                    	add	esi, ecx
  2047                                  btdstr0:
  2048 00001718 4E                      	dec	esi
  2049 00001719 31D2                    	xor	edx, edx
  2050 0000171B F7F3                    	div	ebx
  2051 0000171D 80C230                  	add	dl, 30h
  2052 00001720 8816                    	mov	[esi], dl
  2053 00001722 FEC9                    	dec	cl
  2054 00001724 740C                    	jz	short btdstr2 ; 02/01/2022 (short jump)
  2055 00001726 09C0                    	or	eax, eax
  2056 00001728 75EE                    	jnz	short btdstr0
  2057                                  btdstr1:
  2058 0000172A 4E                      	dec	esi
  2059 0000172B C60620                          mov     byte [esi], 20h ; blank space
  2060 0000172E FEC9                    	dec	cl
  2061 00001730 75F8                    	jnz	short btdstr1
  2062                                  btdstr2:
  2063 00001732 C3                      	ret
  2064                                  
  2065                                  ; Calculate free memory pages on M.A.T.
  2066                                  ; 06/11/2014
  2067                                  ; Temporary Code
  2068                                  ;
  2069                                  
  2070                                  calc_free_mem:
  2071 00001733 31D2                    	xor	edx, edx
  2072                                  	;xor	ecx, ecx
  2073                                  	;mov	cx, [mat_size] ; in pages
  2074                                  	; 02/01/2022
  2075 00001735 8B0D[F06A0000]          	mov	ecx, [mat_size] ; in pages
  2076 0000173B C1E10A                  	shl	ecx, 10	; 1024 dwords per page
  2077 0000173E BE00001000              	mov	esi, MEM_ALLOC_TBL
  2078                                  cfm0:
  2079 00001743 AD                      	lodsd
  2080 00001744 51                      	push	ecx
  2081 00001745 B920000000              	mov	ecx, 32
  2082                                  cfm1:
  2083 0000174A D1E8                    	shr	eax, 1
  2084 0000174C 7301                    	jnc	short cfm2
  2085 0000174E 42                      	inc	edx
  2086                                  cfm2:
  2087 0000174F E2F9                    	loop	cfm1
  2088 00001751 59                      	pop	ecx
  2089 00001752 E2EF                    	loop	cfm0
  2090 00001754 C3                      	ret
  2091                                  
  2092                                  %include 'diskio.inc'  ; 07/03/2015
  2093                              <1> ; Retro UNIX 386 v1.1 Kernel - DISKIO.INC
  2094                              <1> ; Last Modification: 24/12/2021
  2095                              <1> ; 	(Initialized Disk Parameters Data is in 'DISKDATA.INC') 
  2096                              <1> ; 	(Uninitialized Disk Parameters Data is in 'DISKBSS.INC') 
  2097                              <1> 
  2098                              <1> ; DISK I/O SYSTEM - Erdogan Tan (Retro UNIX 386 v1 project)
  2099                              <1> 
  2100                              <1> ; ///////// DISK I/O SYSTEM ///////////////
  2101                              <1> 
  2102                              <1> ; 06/02/2015
  2103                              <1> diskette_io:
  2104 00001755 9C                  <1> 	pushfd
  2105 00001756 0E                  <1> 	push 	cs
  2106 00001757 E809000000          <1> 	call 	DISKETTE_IO_1
  2107 0000175C C3                  <1> 	retn
  2108                              <1> 	
  2109                              <1> ;;;;;; DISKETTE I/O ;;;;;;;;;;;;;;;;;;;; 06/02/2015 ;;;
  2110                              <1> ;//////////////////////////////////////////////////////
  2111                              <1> 
  2112                              <1> ; DISKETTE I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  2113                              <1> ; 20/02/2015
  2114                              <1> ; 06/02/2015 (unix386.s)
  2115                              <1> ; 16/12/2014 - 02/01/2015 (dsectrm2.s)
  2116                              <1> ;
  2117                              <1> ; Code (DELAY) modifications - AWARD BIOS 1999 (ADISK.EQU, COMMON.MAC)
  2118                              <1> ;
  2119                              <1> ; ADISK.EQU
  2120                              <1> 
  2121                              <1> ;----- Wait control constants 
  2122                              <1> 
  2123                              <1> ;amount of time to wait while RESET is active.
  2124                              <1> 
  2125                              <1> WAITCPU_RESET_ON   EQU	21		;Reset on must last at least 14us
  2126                              <1> 					;at 250 KBS xfer rate.
  2127                              <1> 					;see INTEL MCS, 1985, pg. 5-456
  2128                              <1> 
  2129                              <1> WAITCPU_FOR_STATUS EQU	100		;allow 30 microseconds for
  2130                              <1> 					;status register to become valid
  2131                              <1> 					;before re-reading.
  2132                              <1> 
  2133                              <1> ;After sending a byte to NEC, status register may remain
  2134                              <1> ;incorrectly set for 24 us.
  2135                              <1> 
  2136                              <1> WAITCPU_RQM_LOW	   EQU	24		;number of loops to check for
  2137                              <1> 					;RQM low.
  2138                              <1> 
  2139                              <1> ; COMMON.MAC
  2140                              <1> ;
  2141                              <1> ;	Timing macros
  2142                              <1> ;
  2143                              <1> 
  2144                              <1> %macro 		SIODELAY 0 		; SHORT IODELAY
  2145                              <1> 		jmp short $+2
  2146                              <1> %endmacro		
  2147                              <1> 
  2148                              <1> %macro		IODELAY  0		; NORMAL IODELAY
  2149                              <1> 		jmp short $+2
  2150                              <1> 		jmp short $+2
  2151                              <1> %endmacro
  2152                              <1> 
  2153                              <1> %macro		NEWIODELAY 0
  2154                              <1> 		out	0EBh,al
  2155                              <1> %endmacro 
  2156                              <1> 
  2157                              <1> ; (According to) AWARD BIOS 1999 - ATORGS.ASM (dw -> equ, db -> equ)
  2158                              <1> ;;; WAIT_FOR_MEM
  2159                              <1> ;WAIT_FDU_INT_LO	equ	017798		; 2.5 secs in 30 micro units.
  2160                              <1> ;WAIT_FDU_INT_HI	equ	1
  2161                              <1> WAIT_FDU_INT_LH		equ	83334		; 27/02/2015 (2.5 seconds waiting)
  2162                              <1> ;;; WAIT_FOR_PORT
  2163                              <1> ;WAIT_FDU_SEND_LO	equ	16667		; .5 secons in 30 us units.
  2164                              <1> ;WAIT_FDU_SEND_HI	equ	0
  2165                              <1> WAIT_FDU_SEND_LH	equ 	16667		; 27/02/2015	
  2166                              <1> ;Time to wait while waiting for each byte of NEC results = .5
  2167                              <1> ;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  2168                              <1> ;WAIT_FDU_RESULTS_LO	equ	16667		; .5 seconds in 30 micro units.
  2169                              <1> ;WAIT_FDU_RESULTS_HI	equ	0
  2170                              <1> WAIT_FDU_RESULTS_LH	equ	16667  ; 27/02/2015
  2171                              <1> ;;; WAIT_REFRESH
  2172                              <1> ;amount of time to wait for head settle, per unit in parameter
  2173                              <1> ;table = 1 ms.
  2174                              <1> WAIT_FDU_HEAD_SETTLE	equ	33		; 1 ms in 30 micro units.
  2175                              <1> 
  2176                              <1> 
  2177                              <1> ; //////////////// DISKETTE I/O ////////////////
  2178                              <1> 
  2179                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - POSTEQU.INC)
  2180                              <1> 
  2181                              <1> ;----------------------------------------
  2182                              <1> ;	EQUATES USED BY POST AND BIOS	:
  2183                              <1> ;----------------------------------------
  2184                              <1> 
  2185                              <1> ;--------- 8042 KEYBOARD INTERFACE AND DIAGNOSTIC CONTROL REGISTERS ------------
  2186                              <1> ;PORT_A		EQU	060H		; 8042 KEYBOARD SCAN CODE/CONTROL PORT
  2187                              <1> ;PORT_B		EQU	061H		; PORT B READ/WRITE DIAGNOSTIC REGISTER
  2188                              <1> ;REFRESH_BIT	EQU	00010000B	; REFRESH TEST BIT
  2189                              <1> 
  2190                              <1> ;----------------------------------------
  2191                              <1> ;	CMOS EQUATES FOR THIS SYSTEM	:
  2192                              <1> ;-------------------------------------------------------------------------------
  2193                              <1> ;CMOS_PORT	EQU	070H		; I/O ADDRESS OF CMOS ADDRESS PORT
  2194                              <1> ;CMOS_DATA	EQU	071H		; I/O ADDRESS OF CMOS DATA PORT
  2195                              <1> ;NMI		EQU	10000000B	; DISABLE NMI INTERRUPTS MASK -
  2196                              <1> 					;  HIGH BIT OF CMOS LOCATION ADDRESS
  2197                              <1> 
  2198                              <1> ;---------- CMOS TABLE LOCATION ADDRESS'S ## -----------------------------------
  2199                              <1> CMOS_DISKETTE	EQU	010H		; DISKETTE DRIVE TYPE BYTE	      ;
  2200                              <1> ;		EQU	011H		; - RESERVED			      ;C
  2201                              <1> CMOS_DISK	EQU	012H		; FIXED DISK TYPE BYTE		      ;H
  2202                              <1> ;		EQU	013H		; - RESERVED			      ;E
  2203                              <1> CMOS_EQUIP	EQU	014H		; EQUIPMENT WORD LOW BYTE	      ;C
  2204                              <1> 
  2205                              <1> ;---------- DISKETTE EQUATES ---------------------------------------------------
  2206                              <1> INT_FLAG	EQU	10000000B	; INTERRUPT OCCURRENCE FLAG
  2207                              <1> DSK_CHG 	EQU	10000000B	; DISKETTE CHANGE FLAG MASK BIT
  2208                              <1> DETERMINED	EQU	00010000B	; SET STATE DETERMINED IN STATE BITS
  2209                              <1> HOME		EQU	00010000B	; TRACK 0 MASK
  2210                              <1> SENSE_DRV_ST	EQU	00000100B	; SENSE DRIVE STATUS COMMAND
  2211                              <1> TRK_SLAP	EQU	030H		; CRASH STOP (48 TPI DRIVES)
  2212                              <1> QUIET_SEEK	EQU	00AH		; SEEK TO TRACK 10
  2213                              <1> ;MAX_DRV 	EQU	2		; MAX NUMBER OF DRIVES
  2214                              <1> HD12_SETTLE	EQU	15		; 1.2 M HEAD SETTLE TIME
  2215                              <1> HD320_SETTLE	EQU	20		; 320 K HEAD SETTLE TIME
  2216                              <1> MOTOR_WAIT	EQU	37		; 2 SECONDS OF COUNTS FOR MOTOR TURN OFF
  2217                              <1> 
  2218                              <1> ;---------- DISKETTE ERRORS ----------------------------------------------------
  2219                              <1> ;TIME_OUT	EQU	080H		; ATTACHMENT FAILED TO RESPOND
  2220                              <1> ;BAD_SEEK	EQU	040H		; SEEK OPERATION FAILED
  2221                              <1> BAD_NEC 	EQU	020H		; DISKETTE CONTROLLER HAS FAILED
  2222                              <1> BAD_CRC 	EQU	010H		; BAD CRC ON DISKETTE READ
  2223                              <1> MED_NOT_FND	EQU	00CH		; MEDIA TYPE NOT FOUND
  2224                              <1> DMA_BOUNDARY	EQU	009H		; ATTEMPT TO DMA ACROSS 64K BOUNDARY
  2225                              <1> BAD_DMA 	EQU	008H		; DMA OVERRUN ON OPERATION
  2226                              <1> MEDIA_CHANGE	EQU	006H		; MEDIA REMOVED ON DUAL ATTACH CARD
  2227                              <1> RECORD_NOT_FND	EQU	004H		; REQUESTED SECTOR NOT FOUND
  2228                              <1> WRITE_PROTECT	EQU	003H		; WRITE ATTEMPTED ON WRITE PROTECT DISK
  2229                              <1> BAD_ADDR_MARK	EQU	002H		; ADDRESS MARK NOT FOUND
  2230                              <1> BAD_CMD 	EQU	001H		; BAD COMMAND PASSED TO DISKETTE I/O
  2231                              <1> 
  2232                              <1> ;---------- DISK CHANGE LINE EQUATES -------------------------------------------
  2233                              <1> NOCHGLN 	EQU	001H		; NO DISK CHANGE LINE AVAILABLE
  2234                              <1> CHGLN		EQU	002H		; DISK CHANGE LINE AVAILABLE
  2235                              <1> 
  2236                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS ---------------------------------------
  2237                              <1> TRK_CAPA	EQU	00000001B	; 80 TRACK CAPABILITY
  2238                              <1> FMT_CAPA	EQU	00000010B	; MULTIPLE FORMAT CAPABILITY (1.2M)
  2239                              <1> DRV_DET 	EQU	00000100B	; DRIVE DETERMINED
  2240                              <1> MED_DET 	EQU	00010000B	; MEDIA DETERMINED BIT
  2241                              <1> DBL_STEP	EQU	00100000B	; DOUBLE STEP BIT
  2242                              <1> RATE_MSK	EQU	11000000B	; MASK FOR CLEARING ALL BUT RATE
  2243                              <1> RATE_500	EQU	00000000B	; 500 KBS DATA RATE
  2244                              <1> RATE_300	EQU	01000000B	; 300 KBS DATA RATE
  2245                              <1> RATE_250	EQU	10000000B	; 250 KBS DATA RATE
  2246                              <1> STRT_MSK	EQU	00001100B	; OPERATION START RATE MASK
  2247                              <1> SEND_MSK	EQU	11000000B	; MASK FOR SEND RATE BITS
  2248                              <1> 
  2249                              <1> ;---------- MEDIA/DRIVE STATE INDICATORS COMPATIBILITY -------------------------
  2250                              <1> M3D3U		EQU	00000000B	; 360 MEDIA/DRIVE NOT ESTABLISHED
  2251                              <1> M3D1U		EQU	00000001B	; 360 MEDIA,1.2DRIVE NOT ESTABLISHED
  2252                              <1> M1D1U		EQU	00000010B	; 1.2 MEDIA/DRIVE NOT ESTABLISHED
  2253                              <1> MED_UNK 	EQU	00000111B	; NONE OF THE ABOVE
  2254                              <1> 
  2255                              <1> ;---------- INTERRUPT EQUATES --------------------------------------------------
  2256                              <1> ;EOI		EQU	020H		; END OF INTERRUPT COMMAND TO 8259
  2257                              <1> ;INTA00		EQU	020H		; 8259 PORT
  2258                              <1> INTA01		EQU	021H		; 8259 PORT
  2259                              <1> INTB00		EQU	0A0H		; 2ND 8259
  2260                              <1> INTB01		EQU	0A1H		;
  2261                              <1> 
  2262                              <1> ;-------------------------------------------------------------------------------
  2263                              <1> DMA08		EQU	008H		; DMA STATUS REGISTER PORT ADDRESS
  2264                              <1> DMA		EQU	000H		; DMA CH.0 ADDRESS REGISTER PORT ADDRESS
  2265                              <1> DMA18		EQU	0D0H		; 2ND DMA STATUS PORT ADDRESS
  2266                              <1> DMA1		EQU	0C0H		; 2ND DMA CH.0 ADDRESS REGISTER ADDRESS
  2267                              <1> ;-------------------------------------------------------------------------------
  2268                              <1> ;TIMER		EQU	040H		; 8254 TIMER - BASE ADDRESS
  2269                              <1> 
  2270                              <1> ;-------------------------------------------------------------------------------
  2271                              <1> DMA_PAGE	EQU	081H		; START OF DMA PAGE REGISTERS
  2272                              <1> 
  2273                              <1> ; 06/02/2015 (unix386.s, protected mode modifications)
  2274                              <1> ; (unix386.s <-- dsectrm2.s)
  2275                              <1> ; 11/12/2014 (copy from IBM PC-XT Model 286 BIOS - DSEG.INC)
  2276                              <1> 
  2277                              <1> ; 10/12/2014
  2278                              <1> ;
  2279                              <1> ;int40h:
  2280                              <1> ;	pushf
  2281                              <1> ;	push 	cs
  2282                              <1> ;	;cli
  2283                              <1> ;	call 	DISKETTE_IO_1
  2284                              <1> ;	retn
  2285                              <1> 
  2286                              <1> ; DSKETTE ----- 04/21/86 DISKETTE BIOS
  2287                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  2288                              <1> ;
  2289                              <1> 
  2290                              <1> ;-- INT13H ---------------------------------------------------------------------
  2291                              <1> ; DISKETTE I/O
  2292                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO THE 5 1/4 INCH 360 KB,
  2293                              <1> ;	1.2 MB, 720 KB AND 1.44 MB DISKETTE DRIVES.
  2294                              <1> ; INPUT
  2295                              <1> ;	(AH) =  00H RESET DISKETTE SYSTEM
  2296                              <1> ;		HARD RESET TO NEC, PREPARE COMMAND, RECALIBRATE REQUIRED
  2297                              <1> ;		ON ALL DRIVES
  2298                              <1> ;------------------------------------------------------------------------------- 
  2299                              <1> ;	(AH)= 01H  READ THE STATUS OF THE SYSTEM INTO (AH)
  2300                              <1> ;		@DISKETTE_STATUS FROM LAST OPERATION IS USED
  2301                              <1> ;-------------------------------------------------------------------------------
  2302                              <1> ;	REGISTERS FOR READ/WRITE/VERIFY/FORMAT
  2303                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2304                              <1> ;	(DH) - HEAD NUMBER (0-1 ALLOWED, NOT VALUE CHECKED)
  2305                              <1> ;	(CH) - TRACK NUMBER (NOT VALUE CHECKED)
  2306                              <1> ;		MEDIA	DRIVE	TRACK NUMBER
  2307                              <1> ;		320/360	320/360	    0-39
  2308                              <1> ;		320/360	1.2M	    0-39
  2309                              <1> ;		1.2M	1.2M	    0-79
  2310                              <1> ;		720K	720K	    0-79
  2311                              <1> ;		1.44M	1.44M	    0-79	
  2312                              <1> ;	(CL) - 	SECTOR NUMBER (NOT VALUE CHECKED, NOT USED FOR FORMAT)
  2313                              <1> ;		MEDIA	DRIVE	SECTOR NUMBER
  2314                              <1> ;		320/360	320/360	     1-8/9
  2315                              <1> ;		320/360	1.2M	     1-8/9
  2316                              <1> ;		1.2M	1.2M	     1-15
  2317                              <1> ;		720K	720K	     1-9
  2318                              <1> ;		1.44M	1.44M	     1-18		
  2319                              <1> ;	(AL)	NUMBER OF SECTORS (NOT VALUE CHECKED)
  2320                              <1> ;		MEDIA	DRIVE	MAX NUMBER OF SECTORS
  2321                              <1> ;		320/360	320/360	        8/9
  2322                              <1> ;		320/360	1.2M	        8/9
  2323                              <1> ;		1.2M	1.2M		15
  2324                              <1> ;		720K	720K		9
  2325                              <1> ;		1.44M	1.44M		18
  2326                              <1> ;
  2327                              <1> ;	(ES:BX) - ADDRESS OF BUFFER (NOT REQUIRED FOR VERIFY)
  2328                              <1> ;
  2329                              <1> ;-------------------------------------------------------------------------------
  2330                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY
  2331                              <1> ;-------------------------------------------------------------------------------
  2332                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY
  2333                              <1> ;-------------------------------------------------------------------------------
  2334                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS
  2335                              <1> ;-------------------------------------------------------------------------------
  2336                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK
  2337                              <1> ;		(ES,BX) MUST POINT TO THE COLLECTION OF DESIRED ADDRESS FIELDS
  2338                              <1> ;		FOR THE	TRACK. EACH FIELD IS COMPOSED OF 4 BYTES, (C,H,R,N),
  2339                              <1> ;		WHERE C = TRACK NUMBER, H=HEAD NUMBER, R = SECTOR NUMBER, 
  2340                              <1> ;		N= NUMBER OF BYTES PER SECTOR (00=128,01=256,02=512,03=1024),
  2341                              <1> ;		THERE MUST BE ONE ENTRY FOR EVERY SECTOR ON THE TRACK.
  2342                              <1> ;		THIS INFORMATION IS USED TO FIND THE REQUESTED SECTOR DURING 
  2343                              <1> ;		READ/WRITE ACCESS.
  2344                              <1> ;		PRIOR TO FORMATTING A DISKETTE, IF THERE EXISTS MORE THAN
  2345                              <1> ;		ONE SUPPORTED MEDIA FORMAT TYPE WITHIN THE DRIVE IN QUESTION,
  2346                              <1> ;		THEN "SET DASD TYPE" (INT 13H, AH = 17H) OR 'SET MEDIA TYPE'
  2347                              <1> ;		(INT 13H, AH =  18H) MUST BE CALLED TO SET THE DISKETTE TYPE
  2348                              <1> ;		THAT IS TO BE FORMATTED. IF "SET DASD TYPE" OR "SET MEDIA TYPE"
  2349                              <1> ;		IS NOT CALLED, THE FORMAT ROUTINE WILL ASSUME THE 
  2350                              <1> ;		MEDIA FORMAT TO BE THE MAXIMUM CAPACITY OF THE DRIVE.
  2351                              <1> ;
  2352                              <1> ;		THESE PARAMETERS OF DISK BASE MUST BE CHANGED IN ORDER TO
  2353                              <1> ;		FORMAT THE FOLLOWING MEDIAS:
  2354                              <1> ;		---------------------------------------------
  2355                              <1> ;		: MEDIA  :     DRIVE      : PARM 1 : PARM 2 :
  2356                              <1> ;		---------------------------------------------
  2357                              <1> ;		: 320K	 : 320K/360K/1.2M :  50H   :   8    :
  2358                              <1> ;		: 360K	 : 320K/360K/1.2M :  50H   :   9    :
  2359                              <1> ;		: 1.2M	 : 1.2M           :  54H   :  15    :
  2360                              <1> ;		: 720K	 : 720K/1.44M     :  50H   :   9    :
  2361                              <1> ;		: 1.44M	 : 1.44M          :  6CH   :  18    :		  	
  2362                              <1> ;		---------------------------------------------
  2363                              <1> ;		NOTES: - PARM 1 = GAP LENGTH FOR FORMAT
  2364                              <1> ;		       - PARM 2 = EOT (LAST SECTOR ON TRACK)
  2365                              <1> ;		       - DISK BASE IS POINTED BY DISK POINTER LOCATED
  2366                              <1> ;			 AT ABSOLUTE ADDRESS 0:78.
  2367                              <1> ;		       - WHEN FORMAT OPERATIONS ARE COMPLETE, THE PARAMETERS
  2368                              <1> ;			 SHOULD BE RESTORED TO THEIR RESPECTIVE INITIAL VALUES.			
  2369                              <1> ;-------------------------------------------------------------------------------
  2370                              <1> ;	(AH) = 08H READ DRIVE PARAMETERS
  2371                              <1> ;	REGISTERS
  2372                              <1> ;	  INPUT
  2373                              <1> ;	    (DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2374                              <1> ;	  OUTPUT
  2375                              <1> ;	    (ES:DI) POINTS TO DRIVE PARAMETER TABLE
  2376                              <1> ;	    (CH) - LOW ORDER 8 OF 10 BITS MAXIMUM NUMBER OF TRACKS
  2377                              <1> ;	    (CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2378                              <1> ;	           BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2379                              <1> ;	    (DH) - MAXIMUM HEAD NUMBER
  2380                              <1> ;	    (DL) - NUMBER OF DISKETTE DRIVES INSTALLED
  2381                              <1> ;	    (BH) - 0
  2382                              <1> ;	    (BL) - BITS 7 THRU 4 - 0
  2383                              <1> ;	           BITS 3 THRU 0 - VALID DRIVE TYPE VALUE IN CMOS
  2384                              <1> ;	    (AX) - 0
  2385                              <1> ;	 UNDER THE FOLLOWING CIRCUMSTANCES:
  2386                              <1> ;	    (1) THE DRIVE NUMBER IS INVALID,
  2387                              <1> ;	    (2) THE DRIVE TYPE IS UNKNOWN AND CMOS IS NOT PRESENT, 
  2388                              <1> ;	    (3) THE DRIVE TYPE IS UNKNOWN AND CMOS IS BAD,
  2389                              <1> ;	    (4) OR THE DRIVE TYPE IS UNKNOWN AND THE CMOS DRIVE TYPE IS INVALID
  2390                              <1> ;	    THEN ES,AX,BX,CX,DH,DI=0 ; DL=NUMBER OF DRIVES. 
  2391                              <1> ;	    IF NO DRIVES ARE PRESENT THEN: ES,AX,BX,CX,DX,DI=0.
  2392                              <1> ;	    @DISKETTE_STATUS = 0 AND CY IS RESET.
  2393                              <1> ;-------------------------------------------------------------------------------
  2394                              <1> ;	(AH)= 15H  READ DASD TYPE
  2395                              <1> ;	OUTPUT REGISTERS
  2396                              <1> ;	(AH) - ON RETURN IF CARRY FLAG NOT SET, OTHERWISE ERROR	
  2397                              <1> ;		00 - DRIVE NOT PRESENT	
  2398                              <1> ;		01 - DISKETTE, NO CHANGE LINE AVAILABLE
  2399                              <1> ;		02 - DISKETTE, CHANGE LINE AVAILABLE	
  2400                              <1> ;		03 - RESERVED (FIXED DISK)
  2401                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2402                              <1> ;-------------------------------------------------------------------------------
  2403                              <1> ;	(AH)= 16H  DISK CHANGE LINE STATUS
  2404                              <1> ;	OUTPUT REGISTERS
  2405                              <1> ;	(AH) - 00 - DISK CHANGE LINE NOT ACTIVE	
  2406                              <1> ;	       06 - DISK CHANGE LINE ACTIVE & CARRY BIT ON
  2407                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED)
  2408                              <1> ;-------------------------------------------------------------------------------
  2409                              <1> ;	(AH)= 17H  SET DASD TYPE FOR FORMAT
  2410                              <1> ;	INPUT REGISTERS
  2411                              <1> ;	(AL) -	00 - NOT USED	
  2412                              <1> ;		01 - DISKETTE 320/360K IN 360K DRIVE	
  2413                              <1> ;		02 - DISKETTE 360K IN 1.2M DRIVE
  2414                              <1> ;		03 - DISKETTE 1.2M IN 1.2M DRIVE
  2415                              <1> ;		04 - DISKETTE 720K IN 720K DRIVE
  2416                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHECKED:
  2417                              <1> ;	       (DO NOT USE WHEN DISKETTE ATTACH CARD USED)
  2418                              <1> ;-------------------------------------------------------------------------------
  2419                              <1> ;	(AH)= 18H  SET MEDIA TYPE FOR FORMAT
  2420                              <1> ;	INPUT REGISTERS
  2421                              <1> ;	(CH) - LOW ORDER 8 OF 10 BITS MAXIMUM TRACKS
  2422                              <1> ;	(CL) - BITS 7 & 6 - HIGH ORDER TWO BITS OF MAXIMUM TRACKS
  2423                              <1> ;	       BITS 5 THRU 0 - MAXIMUM SECTORS PER TRACK
  2424                              <1> ;	(DL) - DRIVE NUMBER (0-1 ALLOWED, VALUE CHACKED)
  2425                              <1> ;	OUTPUT REGISTERS:
  2426                              <1> ;	(ES:DI) - POINTER TO DRIVE PARAMETERS TABLE FOR THIS MEDIA TYPE,
  2427                              <1> ;		  UNCHANGED IF (AH) IS NON-ZERO
  2428                              <1> ;	(AH) - 00H, CY = 0, TRACK AND SECTORS/TRACK COMBINATION IS SUPPORTED
  2429                              <1> ;	     - 01H, CY = 1, FUNCTION IS NOT AVAILABLE
  2430                              <1> ;	     - 0CH, CY = 1, TRACK AND SECTORS/TRACK COMBINATION IS NOT SUPPORTED
  2431                              <1> ;	     - 80H, CY = 1, TIME OUT (DISKETTE NOT PRESENT)		
  2432                              <1> ;-------------------------------------------------------------------------------
  2433                              <1> ;	DISK CHANGE STATUS IS ONLY CHECKED WHEN A MEDIA SPECIFIED IS OTHER
  2434                              <1> ;	THAN 360 KB DRIVE. IF THE DISK CHANGE LINE IS FOUND TO BE
  2435                              <1> ;	ACTIVE THE FOLLOWING ACTIONS TAKE PLACE:
  2436                              <1> ;		ATTEMPT TO RESET DISK CHANGE LINE TO INACTIVE STATE. 
  2437                              <1> ;		IF ATTEMPT SUCCEEDS SET DASD TYPE FOR FORMAT AND RETURN DISK 
  2438                              <1> ;		CHANGE ERROR CODE
  2439                              <1> ;		IF ATTEMPT FAILS RETURN TIMEOUT ERROR CODE AND SET DASD TYPE 
  2440                              <1> ;		TO A PREDETERMINED STATE INDICATING MEDIA TYPE UNKNOWN.
  2441                              <1> ;	IF THE DISK CHANGE LINE IN INACTIVE PERFORM SET DASD TYPE FOR FORMAT.
  2442                              <1> ;
  2443                              <1> ; DATA VARIABLE -- @DISK_POINTER
  2444                              <1> ;	DOUBLE WORD POINTER TO THE CURRENT SET OF DISKETTE PARAMETERS
  2445                              <1> ;-------------------------------------------------------------------------------
  2446                              <1> ; OUTPUT FOR ALL FUNCTIONS
  2447                              <1> ;	AH = STATUS OF OPERATION
  2448                              <1> ;		STATUS BITS ARE DEFINED IN THE EQUATES FOR @DISKETTE_STATUS
  2449                              <1> ;		VARIABLE IN THE DATA SEGMENT OF THIS MODULE
  2450                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN, EXCEPT FOR READ DASD
  2451                              <1> ;		TYPE AH=(15)).
  2452                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)
  2453                              <1> ;	FOR READ/WRITE/VERIFY
  2454                              <1> ;		DS,BX,DX,CX PRESERVED
  2455                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISKETTE CODE, THE APPROPRIATE 
  2456                              <1> ;		ACTION IS TO RESET THE DISKETTE, THEN RETRY THE OPERATION.
  2457                              <1> ;		ON READ ACCESSES, NO MOTOR START DELAY IS TAKEN, SO THAT 
  2458                              <1> ;		THREE RETRIES ARE REQUIRED ON READS TO ENSURE THAT THE 
  2459                              <1> ;		PROBLEM IS NOT DUE TO MOTOR START-UP.
  2460                              <1> ;-------------------------------------------------------------------------------
  2461                              <1> ;
  2462                              <1> ; DISKETTE STATE MACHINE - ABSOLUTE ADDRESS 40:90 (DRIVE A) & 91 (DRIVE B)
  2463                              <1> ;
  2464                              <1> ;   -----------------------------------------------------------------
  2465                              <1> ;   |       |       |       |       |       |       |       |       |
  2466                              <1> ;   |   7   |   6   |   5   |   4   |   3   |   2   |   1   |   0   |
  2467                              <1> ;   |       |       |       |       |       |       |       |       |
  2468                              <1> ;   -----------------------------------------------------------------
  2469                              <1> ;	|	|	|	|	|	|	|	|
  2470                              <1> ;	|	|	|	|	|	-----------------
  2471                              <1> ;	|	|	|	|	|		|
  2472                              <1> ;	|	|	|	|    RESERVED		|
  2473                              <1> ;	|	|	|	|		  PRESENT STATE
  2474                              <1> ;	|	|	|	|	000: 360K IN 360K DRIVE UNESTABLISHED
  2475                              <1> ;	|	|	|	|	001: 360K IN 1.2M DRIVE UNESTABLISHED
  2476                              <1> ;	|	|	|	|	010: 1.2M IN 1.2M DRIVE UNESTABLISHED
  2477                              <1> ;	|	|	|	|	011: 360K IN 360K DRIVE ESTABLISHED
  2478                              <1> ;	|	|	|	|	100: 360K IN 1.2M DRIVE ESTABLISHED
  2479                              <1> ;	|	|	|	|	101: 1.2M IN 1.2M DRIVE ESTABLISHED
  2480                              <1> ;	|	|	|	|	110: RESERVED
  2481                              <1> ;	|	|	|	|	111: NONE OF THE ABOVE
  2482                              <1> ;	|	|	|	|
  2483                              <1> ;	|	|	|	------>	MEDIA/DRIVE ESTABLISHED
  2484                              <1> ;	|	|	|
  2485                              <1> ;	|	|	-------------->	DOUBLE STEPPING REQUIRED (360K IN 1.2M
  2486                              <1> ;	|	|			DRIVE)
  2487                              <1> ;	|	|
  2488                              <1> ;	------------------------------>	DATA TRANSFER RATE FOR THIS DRIVE:
  2489                              <1> ;
  2490                              <1> ;						00: 500 KBS
  2491                              <1> ;						01: 300 KBS
  2492                              <1> ;						10: 250 KBS
  2493                              <1> ;						11: RESERVED
  2494                              <1> ;
  2495                              <1> ;
  2496                              <1> ;-------------------------------------------------------------------------------
  2497                              <1> ; STATE OPERATION STARTED - ABSOLUTE ADDRESS 40:92 (DRIVE A) & 93 (DRIVE B)
  2498                              <1> ;-------------------------------------------------------------------------------
  2499                              <1> ; PRESENT CYLINDER NUMBER - ABSOLUTE ADDRESS 40:94 (DRIVE A) & 95 (DRIVE B)
  2500                              <1> ;-------------------------------------------------------------------------------
  2501                              <1> 
  2502                              <1> struc MD
  2503 00000000 ??                  <1> 	.SPEC1		resb	1	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2504 00000001 ??                  <1> 	.SPEC2		resb	1	; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2505 00000002 ??                  <1> 	.OFF_TIM	resb	1	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2506 00000003 ??                  <1> 	.BYT_SEC	resb	1	; 512 BYTES/SECTOR
  2507 00000004 ??                  <1> 	.SEC_TRK	resb	1	; EOT (LAST SECTOR ON TRACK)
  2508 00000005 ??                  <1> 	.GAP		resb	1	; GAP LENGTH
  2509 00000006 ??                  <1> 	.DTL		resb	1	; DTL
  2510 00000007 ??                  <1> 	.GAP3		resb	1	; GAP LENGTH FOR FORMAT
  2511 00000008 ??                  <1> 	.FIL_BYT	resb	1	; FILL BYTE FOR FORMAT
  2512 00000009 ??                  <1> 	.HD_TIM		resb	1	; HEAD SETTLE TIME (MILLISECONDS)
  2513 0000000A ??                  <1> 	.STR_TIM	resb	1	; MOTOR START TIME (1/8 SECONDS)
  2514 0000000B ??                  <1> 	.MAX_TRK	resb	1	; MAX. TRACK NUMBER
  2515 0000000C ??                  <1> 	.RATE		resb	1	; DATA TRANSFER RATE
  2516                              <1> endstruc
  2517                              <1> 
  2518                              <1> BIT7OFF	EQU	7FH
  2519                              <1> BIT7ON	EQU	80H
  2520                              <1> 
  2521                              <1> ;;int13h: ; 16/02/2015
  2522                              <1> ;; 16/02/2015 - 21/02/2015
  2523                              <1> int40h:
  2524 0000175D 9C                  <1> 	pushfd
  2525 0000175E 0E                  <1> 	push 	cs
  2526 0000175F E801000000          <1> 	call 	DISKETTE_IO_1
  2527 00001764 C3                  <1> 	retn	
  2528                              <1> 
  2529                              <1> DISKETTE_IO_1:
  2530                              <1> 
  2531 00001765 FB                  <1> 	STI				; INTERRUPTS BACK ON
  2532 00001766 55                  <1> 	PUSH	eBP			; USER REGISTER
  2533 00001767 57                  <1> 	PUSH	eDI			; USER REGISTER
  2534 00001768 52                  <1> 	PUSH	eDX			; HEAD #, DRIVE # OR USER REGISTER
  2535 00001769 53                  <1> 	PUSH	eBX			; BUFFER OFFSET PARAMETER OR REGISTER
  2536 0000176A 51                  <1> 	PUSH	eCX			; TRACK #-SECTOR # OR USER REGISTER
  2537 0000176B 89E5                <1> 	MOV	eBP,eSP			; BP     => PARAMETER LIST DEP. ON AH
  2538                              <1> 					; [BP]   = SECTOR #
  2539                              <1> 					; [BP+1] = TRACK #
  2540                              <1> 					; [BP+2] = BUFFER OFFSET
  2541                              <1> 					; FOR RETURN OF DRIVE PARAMETERS:
  2542                              <1> 					; CL/[BP] = BITS 7&6 HI BITS OF MAX CYL
  2543                              <1> 					; 	    BITS 0-5 MAX SECTORS/TRACK
  2544                              <1> 					; CH/[BP+1] = LOW 8 BITS OF MAX CYL.
  2545                              <1> 					; BL/[BP+2] = BITS 7-4 = 0
  2546                              <1> 					;	      BITS 3-0 = VALID CMOS TYPE
  2547                              <1> 					; BH/[BP+3] = 0
  2548                              <1> 					; DL/[BP+4] = # DRIVES INSTALLED
  2549                              <1> 					; DH/[BP+5] = MAX HEAD #
  2550                              <1> 					; DI/[BP+6] = OFFSET TO DISK BASE
  2551 0000176D 06                  <1> 	push	es ; 06/02/2015	
  2552 0000176E 1E                  <1> 	PUSH	DS			; BUFFER SEGMENT PARM OR USER REGISTER
  2553 0000176F 56                  <1> 	PUSH	eSI			; USER REGISTERS
  2554                              <1> 	;CALL	DDS			; SEGMENT OF BIOS DATA AREA TO DS
  2555                              <1> 	;mov	cx, cs
  2556                              <1> 	;mov	ds, cx
  2557 00001770 66B91000            <1> 	mov	cx, KDATA
  2558 00001774 8ED9                <1>         mov     ds, cx
  2559 00001776 8EC1                <1>         mov     es, cx
  2560                              <1> 
  2561                              <1> 	;CMP	AH,(FNC_TAE-FNC_TAB)/2	; CHECK FOR > LARGEST FUNCTION
  2562 00001778 80FC19              <1> 	cmp	ah,(FNC_TAE-FNC_TAB)/4 ; 18/02/2015
  2563 0000177B 7202                <1> 	JB	short OK_FUNC		; FUNCTION OK
  2564 0000177D B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2565                              <1> OK_FUNC:
  2566 0000177F 80FC01              <1> 	CMP	AH,1			; RESET OR STATUS ?
  2567 00001782 760C                <1> 	JBE	short OK_DRV		; IF RESET OR STATUS DRIVE ALWAYS OK
  2568 00001784 80FC08              <1> 	CMP	AH,8			; READ DRIVE PARMS ?
  2569 00001787 7407                <1> 	JZ	short OK_DRV		; IF SO DRIVE CHECKED LATER
  2570 00001789 80FA01              <1> 	CMP	DL,1			; DRIVES 0 AND 1 OK
  2571 0000178C 7602                <1> 	JBE	short OK_DRV		; IF 0 OR 1 THEN JUMP
  2572 0000178E B414                <1> 	MOV	AH,14H			; REPLACE WITH KNOWN INVALID FUNCTION
  2573                              <1> OK_DRV:
  2574 00001790 31C9                <1> 	xor	ecx, ecx
  2575                              <1> 	;mov	esi, ecx ; 08/02/2015
  2576                              <1> 	; 24/12/2021
  2577 00001792 89CE                <1> 	mov	esi, ecx
  2578 00001794 89CF                <1> 	mov	edi, ecx ; 08/02/2015
  2579 00001796 88E1                <1> 	MOV	CL,AH			; CL = FUNCTION
  2580                              <1> 	;XOR	CH,CH			; CX = FUNCTION
  2581                              <1> 	;SHL	CL, 1			; FUNCTION TIMES 2
  2582 00001798 C0E102              <1> 	SHL	CL, 2 ; 20/02/2015	; FUNCTION TIMES 4 (for 32 bit offset)
  2583 0000179B BB[D3170000]        <1> 	MOV	eBX,FNC_TAB		; LOAD START OF FUNCTION TABLE
  2584 000017A0 01CB                <1> 	ADD	eBX,eCX			; ADD OFFSET INTO TABLE => ROUTINE
  2585 000017A2 88F4                <1> 	MOV	AH,DH			; AX = HEAD #,# OF SECTORS OR DASD TYPE
  2586 000017A4 30F6                <1> 	XOR	DH,DH			; DX = DRIVE #
  2587 000017A6 6689C6              <1> 	MOV	SI,AX			; SI = HEAD #,# OF SECTORS OR DASD TYPE
  2588 000017A9 6689D7              <1> 	MOV     DI,DX                   ; DI = DRIVE #
  2589                              <1> 	;
  2590                              <1> 	; 11/12/2014
  2591 000017AC 8815[C1650000]      <1>         mov     [cfd], dl               ; current floppy drive (for 'GET_PARM')        
  2592                              <1> 	;
  2593 000017B2 8A25[5C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; LOAD STATUS TO AH FOR STATUS FUNCTION
  2594 000017B8 C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; INITIALIZE FOR ALL OTHERS
  2595                              <1> 
  2596                              <1> ;	THROUGHOUT THE DISKETTE BIOS, THE FOLLOWING INFORMATION IS CONTAINED IN
  2597                              <1> ;	THE FOLLOWING MEMORY LOCATIONS AND REGISTERS. NOT ALL DISKETTE BIOS
  2598                              <1> ;	FUNCTIONS REQUIRE ALL OF THESE PARAMETERS.
  2599                              <1> ;
  2600                              <1> ;		DI	: DRIVE #
  2601                              <1> ;		SI-HI	: HEAD #
  2602                              <1> ;		SI-LOW	: # OF SECTORS OR DASD TYPE FOR FORMAT
  2603                              <1> ;		ES	: BUFFER SEGMENT
  2604                              <1> ;		[BP]	: SECTOR #
  2605                              <1> ;		[BP+1]	: TRACK #
  2606                              <1> ;		[BP+2]	: BUFFER OFFSET
  2607                              <1> ;
  2608                              <1> ;	ACROSS CALLS TO SUBROUTINES THE CARRY FLAG (CY=1), WHERE INDICATED IN 
  2609                              <1> ;	SUBROUTINE PROLOGUES, REPRESENTS AN EXCEPTION RETURN (NORMALLY AN ERROR 
  2610                              <1> ;	CONDITION). IN MOST CASES, WHEN CY = 1, @DSKETTE_STATUS CONTAINS THE 
  2611                              <1> ;	SPECIFIC ERROR CODE.
  2612                              <1> ;
  2613                              <1> 					; (AH) = @DSKETTE_STATUS
  2614 000017BF FF13                <1> 	CALL	dWORD [eBX]		; CALL THE REQUESTED FUNCTION
  2615 000017C1 5E                  <1> 	POP	eSI			; RESTORE ALL REGISTERS
  2616 000017C2 1F                  <1> 	POP	DS
  2617 000017C3 07                  <1> 	pop	es	; 06/02/2015
  2618 000017C4 59                  <1> 	POP	eCX
  2619 000017C5 5B                  <1> 	POP	eBX
  2620 000017C6 5A                  <1> 	POP	eDX
  2621 000017C7 5F                  <1> 	POP	eDI
  2622 000017C8 89E5                <1> 	MOV	eBP, eSP
  2623 000017CA 50                  <1> 	PUSH	eAX
  2624 000017CB 9C                  <1> 	PUSHFd
  2625 000017CC 58                  <1> 	POP	eAX
  2626                              <1> 	;MOV	[BP+6], AX
  2627 000017CD 89450C              <1> 	mov	[ebp+12], eax  ; 18/02/2015, flags
  2628 000017D0 58                  <1> 	POP	eAX
  2629 000017D1 5D                  <1> 	POP	eBP
  2630 000017D2 CF                  <1> 	IRETd
  2631                              <1> 
  2632                              <1> ;-------------------------------------------------------------------------------
  2633                              <1> ; DW --> dd (06/02/2015)
  2634 000017D3 [37180000]          <1> FNC_TAB	dd	DSK_RESET		; AH = 00H; RESET
  2635 000017D7 [AC180000]          <1> 	dd	DSK_STATUS		; AH = 01H; STATUS
  2636 000017DB [BC180000]          <1> 	dd	DSK_READ		; AH = 02H; READ
  2637 000017DF [CD180000]          <1> 	dd	DSK_WRITE		; AH = 03H; WRITE
  2638 000017E3 [DE180000]          <1> 	dd	DSK_VERF		; AH = 04H; VERIFY
  2639 000017E7 [EF180000]          <1> 	dd	DSK_FORMAT		; AH = 05H; FORMAT
  2640 000017EB [73190000]          <1> 	dd	FNC_ERR			; AH = 06H; INVALID
  2641 000017EF [73190000]          <1> 	dd	FNC_ERR			; AH = 07H; INVALID
  2642 000017F3 [7F190000]          <1> 	dd	DSK_PARMS		; AH = 08H; READ DRIVE PARAMETERS
  2643 000017F7 [73190000]          <1> 	dd	FNC_ERR			; AH = 09H; INVALID
  2644 000017FB [73190000]          <1> 	dd	FNC_ERR			; AH = 0AH; INVALID
  2645 000017FF [73190000]          <1> 	dd	FNC_ERR			; AH = 0BH; INVALID
  2646 00001803 [73190000]          <1> 	dd	FNC_ERR			; AH = 0CH; INVALID
  2647 00001807 [73190000]          <1> 	dd	FNC_ERR			; AH = 0DH; INVALID
  2648 0000180B [73190000]          <1> 	dd	FNC_ERR			; AH = 0EH; INVALID
  2649 0000180F [73190000]          <1> 	dd	FNC_ERR			; AH = 0FH; INVALID
  2650 00001813 [73190000]          <1> 	dd	FNC_ERR			; AH = 10H; INVALID
  2651 00001817 [73190000]          <1> 	dd	FNC_ERR			; AH = 11H; INVALID
  2652 0000181B [73190000]          <1> 	dd	FNC_ERR			; AH = 12H; INVALID
  2653 0000181F [73190000]          <1> 	dd	FNC_ERR			; AH = 13H; INVALID
  2654 00001823 [73190000]          <1> 	dd	FNC_ERR			; AH = 14H; INVALID
  2655 00001827 [3E1A0000]          <1> 	dd	DSK_TYPE		; AH = 15H; READ DASD TYPE
  2656 0000182B [661A0000]          <1> 	dd	DSK_CHANGE		; AH = 16H; CHANGE STATUS
  2657 0000182F [9F1A0000]          <1> 	dd	FORMAT_SET		; AH = 17H; SET DASD TYPE
  2658 00001833 [201B0000]          <1> 	dd	SET_MEDIA		; AH = 18H; SET MEDIA TYPE	
  2659                              <1> FNC_TAE EQU     $                       ; END
  2660                              <1> 
  2661                              <1> ;-------------------------------------------------------------------------------
  2662                              <1> ; DISK_RESET	(AH = 00H)	
  2663                              <1> ;		RESET THE DISKETTE SYSTEM.
  2664                              <1> ;
  2665                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2666                              <1> ;-------------------------------------------------------------------------------
  2667                              <1> DSK_RESET:
  2668 00001837 66BAF203            <1> 	MOV	DX,03F2H		; ADAPTER CONTROL PORT
  2669 0000183B FA                  <1> 	CLI				; NO INTERRUPTS
  2670 0000183C A0[5A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  2671 00001841 243F                <1> 	AND	AL,00111111B		; KEEP SELECTED AND MOTOR ON BITS
  2672 00001843 C0C004              <1> 	ROL	AL,4			; MOTOR VALUE TO HIGH NIBBLE
  2673                              <1> 					; DRIVE SELECT TO LOW NIBBLE
  2674 00001846 0C08                <1> 	OR	AL,00001000B		; TURN ON INTERRUPT ENABLE
  2675 00001848 EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2676 00001849 C605[596B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  2677                              <1> 	;JMP	$+2			; WAIT FOR I/O
  2678                              <1> 	;JMP	$+2			; WAIT FOR I/O (TO INSURE MINIMUM
  2679                              <1> 					;      PULSE WIDTH)
  2680                              <1> 	; 19/12/2014
  2681                              <1> 	NEWIODELAY
  2154 00001850 E6EB                <2>  out 0EBh,al
  2682                              <1> 
  2683                              <1> 	; 17/12/2014 
  2684                              <1> 	; AWARD BIOS 1999 - RESETDRIVES (ADISK.ASM)
  2685 00001852 B915000000          <1> 	mov	ecx, WAITCPU_RESET_ON	; cx = 21 -- Min. 14 micro seconds !?
  2686                              <1> wdw1:
  2687                              <1> 	NEWIODELAY   ; 27/02/2015
  2154 00001857 E6EB                <2>  out 0EBh,al
  2688 00001859 E2FC                <1> 	loop	wdw1
  2689                              <1> 	;
  2690 0000185B 0C04                <1> 	OR	AL,00000100B		; TURN OFF RESET BIT
  2691 0000185D EE                  <1> 	OUT	DX,AL			; RESET THE ADAPTER
  2692                              <1> 	; 16/12/2014
  2693                              <1> 	IODELAY
  2149 0000185E EB00                <2>  jmp short $+2
  2150 00001860 EB00                <2>  jmp short $+2
  2694                              <1> 	;
  2695                              <1> 	;STI				; ENABLE THE INTERRUPTS
  2696 00001862 E8EC0B0000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  2697 00001867 723A                <1> 	JC	short DR_ERR		; IF ERROR, RETURN IT
  2698 00001869 66B9C000            <1> 	MOV	CX,11000000B		; CL = EXPECTED @NEC_STATUS
  2699                              <1> NXT_DRV:
  2700                              <1> 	;PUSH	CX			; SAVE FOR CALL
  2701                              <1> 	; 24/12/2021
  2702 0000186D 51                  <1> 	push	ecx
  2703 0000186E B8[A2180000]        <1> 	MOV	eAX, DR_POP_ERR 	; LOAD NEC_OUTPUT ERROR ADDRESS
  2704 00001873 50                  <1> 	PUSH	eAX			; "
  2705 00001874 B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  2706 00001876 E8CE0A0000          <1> 	CALL	NEC_OUTPUT
  2707 0000187B 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  2708 0000187C E8020C0000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  2709                              <1> 	;POP	CX			; RESTORE AFTER CALL
  2710                              <1> 	; 24/12/2021
  2711 00001881 59                  <1> 	pop	ecx
  2712 00001882 721F                <1> 	JC	short DR_ERR		; ERROR RETURN
  2713 00001884 3A0D[5D6B0000]      <1> 	CMP	CL, [NEC_STATUS]	; TEST FOR DRIVE READY TRANSITION
  2714 0000188A 7517                <1> 	JNZ	short DR_ERR		; EVERYTHING OK
  2715 0000188C FEC1                <1> 	INC	CL			; NEXT EXPECTED @NEC_STATUS
  2716 0000188E 80F9C3              <1> 	CMP	CL,11000011B		; ALL POSSIBLE DRIVES CLEARED
  2717 00001891 76DA                <1> 	JBE	short NXT_DRV		; FALL THRU IF 11000100B OR >
  2718                              <1> 	;
  2719 00001893 E843030000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2720                              <1> RESBAC:
  2721 00001898 E8D8080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2722                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2723                              <1> 	; 24/12/2021
  2724 0000189D 89F3                <1> 	mov	ebx, esi
  2725 0000189F 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2726 000018A1 C3                  <1> 	RETn		
  2727                              <1> DR_POP_ERR:
  2728                              <1> 	;POP	CX			; CLEAR STACK
  2729                              <1> 	; 24/12/2021
  2730 000018A2 59                  <1> 	pop	ecx
  2731                              <1> DR_ERR:
  2732 000018A3 800D[5C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; SET ERROR CODE
  2733 000018AA EBEC                <1> 	JMP	SHORT RESBAC		; RETURN FROM RESET
  2734                              <1> 
  2735                              <1> ;-------------------------------------------------------------------------------
  2736                              <1> ; DISK_STATUS	(AH = 01H)
  2737                              <1> ;	DISKETTE STATUS.
  2738                              <1> ;
  2739                              <1> ; ON ENTRY:	AH : STATUS OF PREVIOUS OPERATION
  2740                              <1> ;
  2741                              <1> ; ON EXIT:	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF PREVIOUS OPERATION.
  2742                              <1> ;-------------------------------------------------------------------------------
  2743                              <1> DSK_STATUS:
  2744 000018AC 8825[5C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; PUT BACK FOR SETUP END
  2745 000018B2 E8BE080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2746                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2747                              <1> 	; 24/12/2021
  2748 000018B7 89F3                <1> 	mov	ebx, esi
  2749 000018B9 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2750 000018BB C3                  <1> 	RETn		
  2751                              <1> 
  2752                              <1> ;-------------------------------------------------------------------------------
  2753                              <1> ; DISK_READ	(AH = 02H)	
  2754                              <1> ;	DISKETTE READ.
  2755                              <1> ;
  2756                              <1> ; ON ENTRY:	DI	: DRIVE #
  2757                              <1> ;		SI-HI	: HEAD #
  2758                              <1> ;		SI-LOW	: # OF SECTORS
  2759                              <1> ;		ES	: BUFFER SEGMENT
  2760                              <1> ;		[BP]	: SECTOR #
  2761                              <1> ;		[BP+1]	: TRACK #
  2762                              <1> ;		[BP+2]	: BUFFER OFFSET
  2763                              <1> ;
  2764                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2765                              <1> ;-------------------------------------------------------------------------------
  2766                              <1> 
  2767                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2768                              <1> 
  2769                              <1> DSK_READ:
  2770 000018BC 8025[5A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2771 000018C3 66B846E6            <1> 	MOV	AX,0E646H		; AX = NEC COMMAND, DMA COMMAND
  2772 000018C7 E815040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2773 000018CC C3                  <1> 	RETn
  2774                              <1> 
  2775                              <1> ;-------------------------------------------------------------------------------
  2776                              <1> ; DISK_WRITE	(AH = 03H)
  2777                              <1> ;	DISKETTE WRITE.
  2778                              <1> ;
  2779                              <1> ; ON ENTRY:	DI	: DRIVE #
  2780                              <1> ;		SI-HI	: HEAD #
  2781                              <1> ;		SI-LOW	: # OF SECTORS
  2782                              <1> ;		ES	: BUFFER SEGMENT
  2783                              <1> ;		[BP]	: SECTOR #
  2784                              <1> ;		[BP+1]	: TRACK #
  2785                              <1> ;		[BP+2]	: BUFFER OFFSET
  2786                              <1> ;
  2787                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2788                              <1> ;-------------------------------------------------------------------------------
  2789                              <1> 
  2790                              <1> ; 06/02/2015, ES:BX -> EBX (unix386.s)
  2791                              <1> 
  2792                              <1> DSK_WRITE:
  2793 000018CD 66B84AC5            <1> 	MOV	AX,0C54AH		; AX = NEC COMMAND, DMA COMMAND
  2794 000018D1 800D[5A6B0000]80    <1>         OR      byte [MOTOR_STATUS],10000000B ; INDICATE WRITE OPERATION
  2795 000018D8 E804040000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2796 000018DD C3                  <1> 	RETn
  2797                              <1> 
  2798                              <1> ;-------------------------------------------------------------------------------
  2799                              <1> ; DISK_VERF	(AH = 04H)
  2800                              <1> ;	DISKETTE VERIFY.
  2801                              <1> ;
  2802                              <1> ; ON ENTRY:	DI	: DRIVE #
  2803                              <1> ;		SI-HI	: HEAD #
  2804                              <1> ;		SI-LOW	: # OF SECTORS
  2805                              <1> ;		ES	: BUFFER SEGMENT
  2806                              <1> ;		[BP]	: SECTOR #
  2807                              <1> ;		[BP+1]	: TRACK #
  2808                              <1> ;		[BP+2]	: BUFFER OFFSET
  2809                              <1> ;
  2810                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2811                              <1> ;-------------------------------------------------------------------------------
  2812                              <1> DSK_VERF:
  2813 000018DE 8025[5A6B0000]7F    <1> 	AND	byte [MOTOR_STATUS],01111111B ; INDICATE A READ OPERATION
  2814 000018E5 66B842E6            <1> 	MOV	AX,0E642H		; AX = NEC COMMAND, DMA COMMAND
  2815 000018E9 E8F3030000          <1> 	CALL	RD_WR_VF		; COMMON READ/WRITE/VERIFY
  2816 000018EE C3                  <1> 	RETn
  2817                              <1> 
  2818                              <1> ;-------------------------------------------------------------------------------
  2819                              <1> ; DISK_FORMAT	(AH = 05H)
  2820                              <1> ;	DISKETTE FORMAT.
  2821                              <1> ;
  2822                              <1> ; ON ENTRY:	DI	: DRIVE #
  2823                              <1> ;		SI-HI	: HEAD #
  2824                              <1> ;		SI-LOW	: # OF SECTORS
  2825                              <1> ;		ES	: BUFFER SEGMENT
  2826                              <1> ;		[BP]	: SECTOR #
  2827                              <1> ;		[BP+1]	: TRACK #
  2828                              <1> ;		[BP+2]	: BUFFER OFFSET
  2829                              <1> ;		@DISK_POINTER POINTS TO THE PARAMETER TABLE OF THIS DRIVE
  2830                              <1> ;
  2831                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2832                              <1> ;-------------------------------------------------------------------------------
  2833                              <1> DSK_FORMAT:
  2834 000018EF E830030000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  2835 000018F4 E81D050000          <1> 	CALL	FMT_INIT		; ESTABLISH STATE IF UNESTABLISHED
  2836 000018F9 800D[5A6B0000]80    <1>         OR      byte [MOTOR_STATUS], 10000000B ; INDICATE WRITE OPERATION
  2837 00001900 E865050000          <1> 	CALL	MED_CHANGE		; CHECK MEDIA CHANGE AND RESET IF SO
  2838 00001905 725D                <1>         JC      short FM_DON            ; MEDIA CHANGED, SKIP
  2839 00001907 E8CF020000          <1> 	CALL	SEND_SPEC		; SEND SPECIFY COMMAND TO NEC
  2840 0000190C E8C9050000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMPT RATE IS SAME AS LAST RATE
  2841 00001911 7405                <1>         JZ      short FM_WR             ; YES, SKIP SPECIFY COMMAND
  2842 00001913 E8A2050000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO CONTROLLER
  2843                              <1> FM_WR:
  2844 00001918 E84F060000          <1> 	CALL	FMTDMA_SET		; SET UP THE DMA FOR FORMAT
  2845 0000191D 7245                <1>         JC      short FM_DON            ; RETURN WITH ERROR
  2846 0000191F B44D                <1> 	MOV	AH,04DH			; ESTABLISH THE FORMAT COMMAND
  2847 00001921 E8A7060000          <1> 	CALL	NEC_INIT		; INITIALIZE THE NEC
  2848 00001926 723C                <1>         JC      short FM_DON            ; ERROR - EXIT
  2849 00001928 B8[64190000]        <1>         MOV     eAX, FM_DON             ; LOAD ERROR ADDRESS
  2850 0000192D 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  2851 0000192E B203                <1> 	MOV	DL,3			; BYTES/SECTOR VALUE TO NEC
  2852 00001930 E80E090000          <1> 	CALL	GET_PARM
  2853 00001935 E80F0A0000          <1> 	CALL	NEC_OUTPUT
  2854 0000193A B204                <1> 	MOV	DL,4			; SECTORS/TRACK VALUE TO NEC
  2855 0000193C E802090000          <1> 	CALL	GET_PARM
  2856 00001941 E8030A0000          <1> 	CALL	NEC_OUTPUT
  2857 00001946 B207                <1> 	MOV	DL,7			; GAP LENGTH VALUE TO NEC
  2858 00001948 E8F6080000          <1> 	CALL	GET_PARM
  2859 0000194D E8F7090000          <1> 	CALL	NEC_OUTPUT
  2860 00001952 B208                <1> 	MOV	DL,8			; FILLER BYTE TO NEC
  2861 00001954 E8EA080000          <1> 	CALL	GET_PARM
  2862 00001959 E8EB090000          <1> 	CALL	NEC_OUTPUT
  2863 0000195E 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  2864 0000195F E8E5060000          <1> 	CALL	NEC_TERM		; TERMINATE, RECEIVE STATUS, ETC,
  2865                              <1> FM_DON:
  2866 00001964 E8EC020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2867 00001969 E807080000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  2868                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  2869 0000196E 89F3                <1> 	mov	ebx, esi ; 24/12/2021
  2870 00001970 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  2871 00001972 C3                  <1> 	RETn
  2872                              <1> 
  2873                              <1> ;-------------------------------------------------------------------------------
  2874                              <1> ; FNC_ERR
  2875                              <1> ;	INVALID FUNCTION REQUESTED OR INVALID DRIVE: 
  2876                              <1> ;	SET BAD COMMAND IN STATUS.
  2877                              <1> ;
  2878                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  2879                              <1> ;-------------------------------------------------------------------------------
  2880                              <1> FNC_ERR:				; INVALID FUNCTION REQUEST
  2881                              <1> 	;MOV	AX,SI			; RESTORE AL
  2882                              <1> 	; 24/12/2021
  2883 00001973 89F0                <1> 	mov	eax, esi
  2884 00001975 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  2885 00001977 8825[5C6B0000]      <1> 	MOV	[DSKETTE_STATUS],AH	; STORE IN DATA AREA
  2886 0000197D F9                  <1> 	STC				; SET CARRY INDICATING ERROR
  2887 0000197E C3                  <1> 	RETn
  2888                              <1> 
  2889                              <1> ;-------------------------------------------------------------------------------
  2890                              <1> ; DISK_PARMS	(AH = 08H)	
  2891                              <1> ;	READ DRIVE PARAMETERS.
  2892                              <1> ;
  2893                              <1> ; ON ENTRY:	DI : DRIVE #
  2894                              <1> ;
  2895                              <1> ; ON EXIT:	CL/[BP]   = BITS 7 & 6 HI 2 BITS OF MAX CYLINDER
  2896                              <1> ;		            BITS 0-5 MAX SECTORS/TRACK
  2897                              <1> ;		CH/[BP+1] = LOW 8 BITS OF MAX CYLINDER
  2898                              <1> ;		BL/[BP+2] = BITS 7-4 = 0
  2899                              <1> ;		            BITS 3-0 = VALID CMOS DRIVE TYPE
  2900                              <1> ;		BH/[BP+3] = 0
  2901                              <1> ;		DL/[BP+4] = # DRIVES INSTALLED (VALUE CHECKED)
  2902                              <1> ;		DH/[BP+5] = MAX HEAD #
  2903                              <1> ;		DI/[BP+6] = OFFSET TO DISK_BASE
  2904                              <1> ;		ES        = SEGMENT OF DISK_BASE
  2905                              <1> ;		AX        = 0
  2906                              <1> ;
  2907                              <1> ;		NOTE : THE ABOVE INFORMATION IS STORED IN THE USERS STACK AT
  2908                              <1> ;		       THE LOCATIONS WHERE THE MAIN ROUTINE WILL POP THEM
  2909                              <1> ;		       INTO THE APPROPRIATE REGISTERS BEFORE RETURNING TO THE
  2910                              <1> ;		       CALLER.
  2911                              <1> ;-------------------------------------------------------------------------------
  2912                              <1> DSK_PARMS:
  2913 0000197F E8A0020000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  2914                              <1>      ;	MOV	WORD [BP+2],0		; DRIVE TYPE = 0
  2915 00001984 29D2                <1> 	sub     edx, edx ; 20/02/2015
  2916 00001986 895504              <1>         mov	[ebp+4], edx ; 20/02/2015
  2917                              <1>      ;  MOV     AX, [EQUIP_FLAG]        ; LOAD EQUIPMENT FLAG FOR # DISKETTES
  2918                              <1>      ;  AND     AL,11000001B            ; KEEP DISKETTE DRIVE BITS
  2919                              <1>      ;  MOV     DL,2                    ; DISKETTE DRIVES = 2
  2920                              <1>      ;  CMP     AL,01000001B            ; 2 DRIVES INSTALLED ?
  2921                              <1>      ;  JZ      short STO_DL            ; IF YES JUMP
  2922                              <1>      ;  DEC     DL                      ; DISKETTE DRIVES = 1
  2923                              <1>      ;  CMP     AL,00000001B            ; 1 DRIVE INSTALLED ?
  2924                              <1>      ;  JNZ     short NON_DRV           ; IF NO JUMP
  2925                              <1> 	;sub	edx, edx
  2926 00001989 66A1[CE650000]      <1> 	mov     ax, [fd0_type]
  2927 0000198F 6621C0              <1> 	and     ax, ax
  2928 00001992 7473                <1> 	jz      short NON_DRV
  2929 00001994 FEC2                <1> 	inc     dl
  2930 00001996 20E4                <1> 	and     ah, ah
  2931 00001998 7402                <1> 	jz      short STO_DL
  2932 0000199A FEC2                <1> 	inc     dl
  2933                              <1> STO_DL:
  2934                              <1> 	;MOV	[BP+4],DL		; STORE NUMBER OF DRIVES
  2935 0000199C 895508              <1> 	mov	[ebp+8], edx ; 20/02/2015	 	
  2936 0000199F 6683FF01            <1> 	CMP	DI,1			; CHECK FOR VALID DRIVE
  2937 000019A3 7765                <1> 	JA	short NON_DRV1		; DRIVE INVALID
  2938                              <1> 	;MOV	BYTE [BP+5],1		; MAXIMUM HEAD NUMBER =	1
  2939 000019A5 C6450901            <1> 	mov	byte [ebp+9], 1  ; 20/02/2015	
  2940 000019A9 E88C080000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  2941                              <1> 	;;20/02/2015
  2942                              <1> 	;;JC	short CHK_EST		; IF CMOS BAD CHECKSUM ESTABLISHED
  2943                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE TYPE
  2944 000019AE 7412                <1> 	JZ	short CHK_EST		; JUMP IF SO
  2945 000019B0 E8FD010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2946 000019B5 720B                <1> 	JC	short CHK_EST		; TYPE NOT IN TABLE (POSSIBLE BAD CMOS)
  2947                              <1> 	;MOV	[BP+2],AL		; STORE VALID CMOS DRIVE TYPE
  2948 000019B7 884504              <1>         mov	[ebp+4], al ; 06/02/2015
  2949 000019BA 8A4B04              <1> 	MOV     CL, [eBX+MD.SEC_TRK]     ; GET SECTOR/TRACK
  2950 000019BD 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]     ; GET MAX. TRACK NUMBER
  2951 000019C0 EB36                <1> 	JMP	SHORT STO_CX		; CMOS GOOD, USE CMOS
  2952                              <1> CHK_EST:
  2953 000019C2 8AA7[696B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; LOAD STATE FOR THIS DRIVE
  2954 000019C8 F6C410              <1> 	TEST	AH,MED_DET		; CHECK FOR ESTABLISHED STATE
  2955 000019CB 743D                <1> 	JZ	short NON_DRV1		; CMOS BAD/INVALID OR UNESTABLISHED
  2956                              <1> USE_EST:
  2957 000019CD 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE STATE
  2958 000019D0 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  2959 000019D3 7555                <1> 	JNE	short USE_EST2		; NO, GO CHECK OTHER RATE
  2960                              <1> 
  2961                              <1> ;-----	DATA RATE IS 250 KBS, TRY 360 KB TABLE FIRST
  2962                              <1> 
  2963 000019D5 B001                <1> 	MOV	AL,01			; DRIVE TYPE 1 (360KB)
  2964 000019D7 E8D6010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2965 000019DC 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2966 000019DF 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2967 000019E2 F687[696B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; 80 TRACK ?
  2968 000019E9 740D                <1> 	JZ	short STO_CX		; MUST BE 360KB DRIVE 
  2969                              <1> 
  2970                              <1> ;-----	IT IS 1.44 MB DRIVE
  2971                              <1> 
  2972                              <1> PARM144:
  2973 000019EB B004                <1> 	MOV	AL,04			; DRIVE TYPE 4 (1.44MB)
  2974 000019ED E8C0010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  2975 000019F2 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  2976 000019F5 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  2977                              <1> STO_CX:
  2978 000019F8 894D00              <1> 	MOV	[eBP],eCX		; SAVE POINTER IN STACK FOR RETURN
  2979                              <1> ES_DI:
  2980                              <1> 	;MOV	[BP+6],BX		; ADDRESS OF MEDIA/DRIVE PARM TABLE 
  2981 000019FB 895D0C              <1> 	mov	[ebp+12], ebx ; 06/02/2015
  2982                              <1> 	;MOV	AX,CS			; SEGMENT MEDIA/DRIVE PARAMETER TABLE
  2983                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  2984                              <1> DP_OUT:
  2985 000019FE E852020000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  2986                              <1> 	;XOR	AX,AX			; CLEAR
  2987                              <1> 	; 24/12/2021
  2988 00001A03 31C0                <1> 	xor	eax, eax
  2989 00001A05 F8                  <1> 	CLC
  2990 00001A06 C3                  <1> 	RETn
  2991                              <1> 
  2992                              <1> ;-----	NO DRIYE PRESENT HANDLER
  2993                              <1> 
  2994                              <1> NON_DRV:
  2995                              <1> 	;MOV	BYTE [BP+4],0		; CLEAR NUMBER OF DRIVES
  2996 00001A07 895508              <1> 	mov	[ebp+8], edx ; 0 ; 20/02/2015
  2997                              <1> NON_DRV1:
  2998 00001A0A 6681FF8000          <1> 	CMP	DI,80H			; CHECK FOR FIXED MEDIA TYPE REQUEST
  2999 00001A0F 720B                <1> 	JB	short NON_DRV2		; CONTINUE IF NOT REQUEST FALL THROUGH
  3000                              <1> 
  3001                              <1> ;-----	FIXED DISK REQUEST FALL THROUGH ERROR
  3002                              <1> 	
  3003 00001A11 E83F020000          <1> 	CALL	XLAT_OLD		; ELSE TRANSLATE TO COMPATIBLE MODE
  3004                              <1> 	;MOV	AX,SI			; RESTORE AL
  3005 00001A16 89F0                <1> 	mov	eax, esi ; 24/12/2021
  3006 00001A18 B401                <1> 	MOV	AH,BAD_CMD		; SET BAD COMMAND ERROR
  3007 00001A1A F9                  <1> 	STC
  3008 00001A1B C3                  <1> 	RETn
  3009                              <1> 
  3010                              <1> NON_DRV2:
  3011                              <1> 	;XOR	AX,AX			; CLEAR PARMS IF NO DRIVES OR CMOS BAD
  3012 00001A1C 31C0                <1> 	xor	eax, eax	
  3013 00001A1E 66894500            <1> 	MOV	[eBP],AX		; TRACKS, SECTORS/TRACK = 0
  3014                              <1> 	;MOV	[BP+5],AH		; HEAD = 0
  3015 00001A22 886509              <1> 	mov	[ebp+9], ah ; 06/02/2015
  3016                              <1> 	;MOV	[BP+6],AX		; OFFSET TO DISK_BASE = 0
  3017 00001A25 89450C              <1> 	mov	[ebp+12], eax
  3018                              <1> 	;MOV	ES,AX			; ES IS SEGMENT OF TABLE
  3019 00001A28 EBD4                <1> 	JMP	SHORT DP_OUT
  3020                              <1> 
  3021                              <1> ;-----	DATA RATE IS EITHER 300 KBS OR 500 KBS, TRY 1.2 MB TABLE FIRST
  3022                              <1> 
  3023                              <1> USE_EST2:
  3024 00001A2A B002                <1> 	MOV	AL,02			; DRIVE TYPE 2 (1.2MB)
  3025 00001A2C E881010000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3026 00001A31 8A4B04              <1>         MOV     CL, [eBX+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3027 00001A34 8A6B0B              <1>         MOV     CH, [eBX+MD.MAX_TRK]    ; GET MAX. TRACK NUMBER
  3028 00001A37 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3029 00001A3A 74BC                <1> 	JZ	short STO_CX		; MUST BE 1.2MB DRIVE
  3030 00001A3C EBAD                <1> 	JMP	SHORT PARM144		; ELSE, IT IS 1.44MB DRIVE 
  3031                              <1> 
  3032                              <1> ;-------------------------------------------------------------------------------
  3033                              <1> ; DISK_TYPE (AH = 15H)	
  3034                              <1> ;	THIS ROUTINE RETURNS THE TYPE OF MEDIA INSTALLED.
  3035                              <1> ;
  3036                              <1> ;  ON ENTRY:	DI = DRIVE #
  3037                              <1> ;
  3038                              <1> ;  ON EXIT:	AH = DRIVE TYPE, CY=0
  3039                              <1> ;-------------------------------------------------------------------------------
  3040                              <1> DSK_TYPE:
  3041 00001A3E E8E1010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3042 00001A43 8A87[696B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET PRESENT STATE INFORMATION
  3043 00001A49 08C0                <1> 	OR	AL,AL			; CHECK FOR NO DRIVE
  3044 00001A4B 7415                <1> 	JZ	short NO_DRV
  3045 00001A4D B401                <1> 	MOV	AH,NOCHGLN		; NO CHANGE LINE FOR 40 TRACK DRIVE
  3046 00001A4F A801                <1> 	TEST	AL,TRK_CAPA		; IS THIS DRIVE AN 80 TRACK DRIVE?
  3047 00001A51 7402                <1> 	JZ	short DT_BACK			; IF NO JUMP
  3048 00001A53 B402                <1> 	MOV	AH,CHGLN		; CHANGE LINE FOR 80 TRACK DRIVE
  3049                              <1> DT_BACK:
  3050                              <1> 	;PUSH	AX			; SAVE RETURN VALUE
  3051 00001A55 50                  <1> 	push	eax ; 24/12/2021
  3052 00001A56 E8FA010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3053                              <1> 	;POP	AX			; RESTORE RETURN VALUE
  3054 00001A5B 58                  <1> 	pop	eax ; 24/12/2021
  3055 00001A5C F8                  <1> 	CLC				; NO ERROR
  3056                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3057                              <1> 	; 24/12/2021
  3058 00001A5D 89F3                <1> 	mov	ebx, esi
  3059 00001A5F 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3060 00001A61 C3                  <1> 	RETn
  3061                              <1> NO_DRV:	
  3062 00001A62 30E4                <1> 	XOR	AH,AH			; NO DRIVE PRESENT OR UNKNOWN
  3063 00001A64 EBEF                <1> 	JMP	SHORT DT_BACK
  3064                              <1> 
  3065                              <1> ;-------------------------------------------------------------------------------
  3066                              <1> ; DISK_CHANGE	(AH = 16H)
  3067                              <1> ;	THIS ROUTINE RETURNS THE STATE OF THE DISK CHANGE LINE.
  3068                              <1> ;
  3069                              <1> ; ON ENTRY:	DI = DRIVE #
  3070                              <1> ;
  3071                              <1> ; ON EXIT:	AH = @DSKETTE_STATUS
  3072                              <1> ;		     00 - DISK CHANGE LINE INACTIVE, CY = 0
  3073                              <1> ;		     06 - DISK CHANGE LINE ACTIVE, CY = 1
  3074                              <1> ;-------------------------------------------------------------------------------
  3075                              <1> DSK_CHANGE:
  3076 00001A66 E8B9010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3077 00001A6B 8A87[696B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET MEDIA STATE INFORMATION
  3078 00001A71 08C0                <1> 	OR	AL,AL			; DRIVE PRESENT ?
  3079 00001A73 7421                <1> 	JZ	short DC_NON		; JUMP IF NO DRIVE
  3080 00001A75 A801                <1> 	TEST	AL,TRK_CAPA		; 80 TRACK DRIVE ?
  3081 00001A77 7407                <1> 	JZ	short SETIT		; IF SO , CHECK CHANGE LINE
  3082                              <1> DC0:
  3083 00001A79 E8600A0000          <1>         CALL    READ_DSKCHNG            ; GO CHECK STATE OF DISK CHANGE LINE
  3084 00001A7E 7407                <1> 	JZ	short FINIS		; CHANGE LINE NOT ACTIVE
  3085                              <1> 
  3086 00001A80 C605[5C6B0000]06    <1> SETIT:	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; INDICATE MEDIA REMOVED
  3087                              <1> 
  3088 00001A87 E8C9010000          <1> FINIS:	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3089 00001A8C E8E4060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3090                              <1> 	;MOV	BX,SI			; GET SAVED AL TO BL
  3091                              <1> 	; 24/12/2021
  3092 00001A91 89F3                <1> 	mov	ebx, esi
  3093 00001A93 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3094 00001A95 C3                  <1> 	RETn
  3095                              <1> DC_NON:
  3096 00001A96 800D[5C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; SET TIMEOUT, NO DRIVE
  3097 00001A9D EBE8                <1> 	JMP	SHORT FINIS
  3098                              <1> 
  3099                              <1> ;-------------------------------------------------------------------------------
  3100                              <1> ; FORMAT_SET	(AH = 17H)
  3101                              <1> ;	THIS ROUTINE IS USED TO ESTABLISH THE TYPE OF MEDIA TO BE USED
  3102                              <1> ;	FOR THE FOLLOWING FORMAT OPERATION.
  3103                              <1> ;
  3104                              <1> ; ON ENTRY:	SI LOW = DASD TYPE FOR FORMAT
  3105                              <1> ;		DI     = DRIVE #
  3106                              <1> ;
  3107                              <1> ; ON EXIT:	@DSKETTE_STATUS REFLECTS STATUS
  3108                              <1> ;		AH = @DSKETTE_STATUS
  3109                              <1> ;		CY = 1 IF ERROR
  3110                              <1> ;-------------------------------------------------------------------------------
  3111                              <1> FORMAT_SET:
  3112 00001A9F E880010000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3113                              <1> 	;PUSH	SI			; SAVE DASD TYPE
  3114                              <1> 	; 24/12/2021
  3115 00001AA4 56                  <1> 	push	esi
  3116 00001AA5 6689F0              <1> 	MOV	AX,SI			; AH = ? , AL , DASD TYPE
  3117 00001AA8 30E4                <1> 	XOR	AH,AH			; AH , 0 , AL , DASD TYPE
  3118 00001AAA 6689C6              <1> 	MOV	SI,AX			; SI = DASD TYPE
  3119 00001AAD 80A7[696B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3120 00001AB4 664E                <1> 	DEC	SI			; CHECK FOR 320/360K MEDIA & DRIVE
  3121 00001AB6 7509                <1> 	JNZ	short NOT_320		; BYPASS IF NOT
  3122 00001AB8 808F[696B0000]90    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_250 ; SET TO 320/360
  3123 00001ABF EB48                <1> 	JMP	SHORT S0
  3124                              <1> NOT_320:
  3125 00001AC1 E8A4030000          <1> 	CALL	MED_CHANGE		; CHECK FOR TIME_OUT
  3126 00001AC6 803D[5C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT
  3127 00001ACD 743A                <1> 	JZ	short S0		; IF TIME OUT TELL CALLER
  3128                              <1> S3:
  3129 00001ACF 664E                <1> 	DEC	SI			; CHECK FOR 320/360K IN 1.2M DRIVE
  3130 00001AD1 7509                <1> 	JNZ	short NOT_320_12	; BYPASS IF NOT
  3131 00001AD3 808F[696B0000]70    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+DBL_STEP+RATE_300 ; SET STATE
  3132 00001ADA EB2D                <1> 	JMP	SHORT S0
  3133                              <1> NOT_320_12:
  3134 00001ADC 664E                <1> 	DEC	SI			; CHECK FOR 1.2M MEDIA IN 1.2M DRIVE
  3135 00001ADE 7509                <1> 	JNZ	short NOT_12		; BYPASS IF NOT
  3136 00001AE0 808F[696B0000]10    <1> 	OR	byte [DSK_STATE+eDI], MED_DET+RATE_500 ; SET STATE VARIABLE
  3137 00001AE7 EB20                <1> 	JMP	SHORT S0		; RETURN TO CALLER
  3138                              <1> NOT_12:	
  3139 00001AE9 664E                <1> 	DEC	SI			; CHECK FOR SET DASD TYPE 04
  3140 00001AEB 752A                <1> 	JNZ	short FS_ERR		; BAD COMMAND EXIT IF NOT VALID TYPE
  3141                              <1> 
  3142 00001AED F687[696B0000]04    <1> 	TEST	byte [DSK_STATE+eDI], DRV_DET ; DRIVE DETERMINED ?
  3143 00001AF4 740B                <1> 	JZ	short ASSUME		; IF STILL NOT DETERMINED ASSUME
  3144 00001AF6 B050                <1> 	MOV	AL,MED_DET+RATE_300
  3145 00001AF8 F687[696B0000]02    <1>         TEST    byte [DSK_STATE+eDI], FMT_CAPA ; MULTIPLE FORMAT CAPABILITY ?
  3146 00001AFF 7502                <1> 	JNZ	short OR_IT_IN		; IF 1.2 M THEN DATA RATE 300
  3147                              <1> ASSUME:
  3148 00001B01 B090                <1> 	MOV	AL,MED_DET+RATE_250	; SET UP
  3149                              <1> OR_IT_IN:
  3150 00001B03 0887[696B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; OR IN THE CORRECT STATE
  3151                              <1> S0:
  3152 00001B09 E847010000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3153 00001B0E E862060000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3154                              <1> 	;POP	BX			; GET SAVED AL TO BL
  3155                              <1> 	; 24/12/2021
  3156 00001B13 5B                  <1> 	pop	ebx
  3157 00001B14 88D8                <1> 	MOV	AL,BL			; PUT BACK FOR RETURN
  3158 00001B16 C3                  <1> 	RETn
  3159                              <1> FS_ERR:
  3160 00001B17 C605[5C6B0000]01    <1> 	MOV	byte [DSKETTE_STATUS], BAD_CMD ; UNKNOWN STATE,BAD COMMAND
  3161 00001B1E EBE9                <1> 	JMP	SHORT S0
  3162                              <1> 
  3163                              <1> ;-------------------------------------------------------------------------------
  3164                              <1> ; SET_MEDIA	(AH = 18H)
  3165                              <1> ;	THIS ROUTINE SETS THE TYPE OF MEDIA AND DATA RATE 
  3166                              <1> ;	TO BE USED FOR THE FOLLOWING FORMAT OPERATION.
  3167                              <1> ;
  3168                              <1> ; ON ENTRY:
  3169                              <1> ;	[BP]	= SECTOR PER TRACK
  3170                              <1> ;	[BP+1]	= TRACK #
  3171                              <1> ;	DI	= DRIVE #
  3172                              <1> ;
  3173                              <1> ; ON EXIT:
  3174                              <1> ;	@DSKETTE_STATUS REFLECTS STATUS
  3175                              <1> ;	IF NO ERROR:
  3176                              <1> ;		AH = 0
  3177                              <1> ;		CY = 0
  3178                              <1> ;		ES = SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3179                              <1> ;		DI/[BP+6] = OFFSET OF MEDIA/DRIVE PARAMETER TABLE
  3180                              <1> ;	IF ERROR:	
  3181                              <1> ;		AH = @DSKETTE_STATUS
  3182                              <1> ;		CY = 1
  3183                              <1> ;-------------------------------------------------------------------------------
  3184                              <1> SET_MEDIA:
  3185 00001B20 E8FF000000          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3186 00001B25 F687[696B0000]01    <1>         TEST    byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR CHANGE LINE AVAILABLE
  3187 00001B2C 7415                <1> 	JZ	short SM_CMOS		; JUMP IF 40 TRACK DRIVE
  3188 00001B2E E837030000          <1> 	CALL	MED_CHANGE		; RESET CHANGE LINE
  3189 00001B33 803D[5C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS], TIME_OUT ; IF TIME OUT TELL CALLER
  3190 00001B3A 746B                <1> 	JE	short SM_RTN
  3191 00001B3C C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS], 0 ; CLEAR STATUS
  3192                              <1> SM_CMOS:
  3193 00001B43 E8F2060000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3194                              <1> 	;;20/02/2015
  3195                              <1> 	;;JC	short MD_NOT_FND	; ERROR IN CMOS
  3196                              <1> 	;;OR	AL,AL			; TEST FOR NO DRIVE
  3197 00001B48 745D                <1> 	JZ	short SM_RTN		; RETURN IF SO
  3198 00001B4A E863000000          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL
  3199 00001B4F 7231                <1> 	JC	short MD_NOT_FND	; TYPE NOT IN TABLE (BAD CMOS)
  3200 00001B51 57                  <1> 	PUSH	eDI			; SAVE REG.
  3201 00001B52 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR. TYPE TABLE
  3202 00001B54 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3203                              <1> DR_SEARCH:
  3204 00001B59 8AA3[4C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3205 00001B5F 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3206 00001B62 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH ?
  3207 00001B64 7516                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT DRIVE TYPE
  3208                              <1> DR_FND:
  3209 00001B66 8BBB[4D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAM TABLE
  3210                              <1> MD_SEARCH:
  3211 00001B6C 8A6704              <1>         MOV     AH, [eDI+MD.SEC_TRK]    ; GET SECTOR/TRACK
  3212 00001B6F 386500              <1> 	CMP	[eBP],AH		; MATCH?
  3213 00001B72 7508                <1> 	JNE	short NXT_MD		; NO, CHECK NEXT MEDIA
  3214 00001B74 8A670B              <1>         MOV     AH, [eDI+MD.MAX_TRK]    ; GET MAX. TRACK #
  3215 00001B77 386501              <1> 	CMP 	[eBP+1],AH		; MATCH?
  3216 00001B7A 740F                <1> 	JE	short MD_FND		; YES, GO GET RATE
  3217                              <1> NXT_MD:
  3218                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3219 00001B7C 83C305              <1>         add	ebx, 5 ; 18/02/2015
  3220 00001B7F E2D8                <1> 	LOOP    DR_SEARCH
  3221 00001B81 5F                  <1> 	POP	eDI			; RESTORE REG.
  3222                              <1> MD_NOT_FND:
  3223 00001B82 C605[5C6B0000]0C    <1> 	MOV	byte [DSKETTE_STATUS], MED_NOT_FND ; ERROR, MEDIA TYPE NOT FOUND
  3224 00001B89 EB1C                <1> 	JMP	SHORT SM_RTN		; RETURN
  3225                              <1> MD_FND:
  3226 00001B8B 8A470C              <1>         MOV     AL, [eDI+MD.RATE]       ; GET RATE
  3227 00001B8E 3C40                <1> 	CMP	AL,RATE_300		; DOUBLE STEP REQUIRED FOR RATE 300
  3228 00001B90 7502                <1> 	JNE	short MD_SET
  3229 00001B92 0C20                <1> 	OR	AL,DBL_STEP
  3230                              <1> MD_SET:
  3231                              <1> 	;MOV	[BP+6],DI		; SAVE TABLE POINTER IN STACK
  3232 00001B94 897D0C              <1> 	mov	[ebp+12], edi ; 18/02/2015
  3233 00001B97 0C10                <1> 	OR	AL,MED_DET		; SET MEDIA ESTABLISHED
  3234 00001B99 5F                  <1> 	POP	eDI
  3235 00001B9A 80A7[696B0000]0F    <1> 	AND	byte [DSK_STATE+eDI], ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR STATE
  3236 00001BA1 0887[696B0000]      <1> 	OR	[DSK_STATE+eDI], AL
  3237                              <1> 	;MOV	AX, CS			; SEGMENT OF MEDIA/DRIVE PARAMETER TABLE
  3238                              <1> 	;MOV	ES, AX			; ES IS SEGMENT OF TABLE
  3239                              <1> SM_RTN:
  3240 00001BA7 E8A9000000          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3241 00001BAC E8C4050000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3242 00001BB1 C3                  <1> 	RETn
  3243                              <1> 
  3244                              <1> ;----------------------------------------------------------------
  3245                              <1> ; DR_TYPE_CHECK							:
  3246                              <1> ;	CHECK IF THE GIVEN DRIVE TYPE IN REGISTER (AL)		:
  3247                              <1> ;	IS SUPPORTED IN BIOS DRIVE TYPE TABLE			:
  3248                              <1> ; ON ENTRY:							:
  3249                              <1> ;	AL = DRIVE TYPE						:
  3250                              <1> ; ON EXIT:							:
  3251                              <1> ;	CS = SEGMENT MEDIA/DRIVE PARAMETER TABLE (CODE)		:
  3252                              <1> ;	CY = 0 	DRIVE TYPE SUPPORTED				:
  3253                              <1> ;	     BX = OFFSET TO MEDIA/DRIVE PARAMETER TABLE		:
  3254                              <1> ;	CY = 1	DRIVE TYPE NOT SUPPORTED 			:
  3255                              <1> ; REGISTERS ALTERED: eBX						:
  3256                              <1> ;----------------------------------------------------------------		
  3257                              <1> DR_TYPE_CHECK:
  3258                              <1> 	;PUSH	AX			
  3259                              <1> 	; 24/12/2021
  3260 00001BB2 50                  <1> 	push	eax
  3261 00001BB3 51                  <1> 	PUSH	eCX
  3262 00001BB4 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3263 00001BB6 B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3264                              <1> TYPE_CHK:	
  3265 00001BBB 8AA3[4C650000]      <1> 	MOV	AH,[DR_TYPE+eBX]	; GET DRIVE TYPE
  3266 00001BC1 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3267 00001BC3 740D                <1> 	JE	short DR_TYPE_VALID	; YES, RETURN WITH CARRY RESET
  3268                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3269 00001BC5 83C305              <1>         add	ebx, 5	; 16/02/2015 (32 bit address modification)
  3270 00001BC8 E2F1                <1> 	LOOP    TYPE_CHK
  3271                              <1> 	;
  3272 00001BCA BB[AB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44MB fd parameter table
  3273                              <1> 					; Default for GET_PARM (11/12/2014)
  3274                              <1> 	;
  3275 00001BCF F9                  <1> 	STC				; DRIVE TYPE NOT FOUND IN TABLE
  3276 00001BD0 EB06                <1> 	JMP	SHORT TYPE_RTN
  3277                              <1> DR_TYPE_VALID:
  3278 00001BD2 8B9B[4D650000]      <1> 	MOV	eBX,[DR_TYPE+eBX+1] 	; BX = MEDIA TABLE
  3279                              <1> TYPE_RTN:
  3280 00001BD8 59                  <1> 	POP	eCX
  3281                              <1> 	;POP	AX
  3282                              <1> 	; 24/12/2021
  3283 00001BD9 58                  <1> 	pop	eax
  3284 00001BDA C3                  <1> 	RETn	
  3285                              <1> 		
  3286                              <1> ;----------------------------------------------------------------
  3287                              <1> ; SEND_SPEC							:
  3288                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3289                              <1> ;	THE DRIVE PARAMETER TABLE POINTED BY @DISK_POINTER	:
  3290                              <1> ; ON ENTRY:	@DISK_POINTER = DRIVE PARAMETER TABLE		:
  3291                              <1> ; ON EXIT:	NONE						:	
  3292                              <1> ; REGISTERS ALTERED: CX, DX					:
  3293                              <1> ;----------------------------------------------------------------		
  3294                              <1> SEND_SPEC:
  3295 00001BDB 50                  <1> 	PUSH	eAX			; SAVE AX
  3296 00001BDC B8[021C0000]        <1> 	MOV	eAX, SPECBAC		; LOAD ERROR ADDRESS
  3297 00001BE1 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3298 00001BE2 B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3299 00001BE4 E860070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3300 00001BE9 28D2                <1> 	SUB	DL,DL			; FIRST SPECIFY BYTE
  3301 00001BEB E853060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3302 00001BF0 E854070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3303 00001BF5 B201                <1> 	MOV	DL,1			; SECOND SPECIFY BYTE
  3304 00001BF7 E847060000          <1> 	CALL	GET_PARM		; GET PARAMETER TO AH
  3305 00001BFC E848070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3306 00001C01 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3307                              <1> SPECBAC:
  3308 00001C02 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3309 00001C03 C3                  <1> 	RETn
  3310                              <1> 
  3311                              <1> ;----------------------------------------------------------------
  3312                              <1> ; SEND_SPEC_MD							:
  3313                              <1> ;	SEND THE SPECIFY COMMAND TO CONTROLLER USING DATA FROM	:
  3314                              <1> ;	THE MEDIA/DRIVE PARAMETER TABLE POINTED BY (CS:BX)	:
  3315                              <1> ; ON ENTRY:	CS:BX = MEDIA/DRIVE PARAMETER TABLE		:
  3316                              <1> ; ON EXIT:	NONE						:	
  3317                              <1> ; REGISTERS ALTERED: AX						:
  3318                              <1> ;----------------------------------------------------------------		
  3319                              <1> SEND_SPEC_MD:
  3320 00001C04 50                  <1> 	PUSH	eAX			; SAVE RATE DATA
  3321 00001C05 B8[221C0000]        <1> 	MOV	eAX, SPEC_ESBAC		; LOAD ERROR ADDRESS
  3322 00001C0A 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  3323 00001C0B B403                <1> 	MOV	AH,03H			; SPECIFY COMMAND
  3324 00001C0D E837070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3325 00001C12 8A23                <1>         MOV     AH, [eBX+MD.SPEC1]      ; GET 1ST SPECIFY BYTE
  3326 00001C14 E830070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3327 00001C19 8A6301              <1>         MOV     AH, [eBX+MD.SPEC2]      ; GET SECOND SPECIFY BYTE
  3328 00001C1C E828070000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE COMMAND
  3329 00001C21 58                  <1> 	POP	eAX			; POP ERROR RETURN
  3330                              <1> SPEC_ESBAC:
  3331 00001C22 58                  <1> 	POP	eAX			; RESTORE ORIGINAL AX VALUE
  3332 00001C23 C3                  <1> 	RETn
  3333                              <1> 
  3334                              <1> ;-------------------------------------------------------------------------------
  3335                              <1> ; XLAT_NEW  
  3336                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM COMPATIBLE
  3337                              <1> ;	MODE TO NEW ARCHITECTURE.
  3338                              <1> ;
  3339                              <1> ; ON ENTRY:	DI = DRIVE #
  3340                              <1> ;-------------------------------------------------------------------------------
  3341                              <1> XLAT_NEW:
  3342 00001C24 83FF01              <1> 	CMP	eDI,1				; VALID DRIVE
  3343 00001C27 7725                <1> 	JA	short XN_OUT			; IF INVALID BACK
  3344 00001C29 80BF[696B0000]00    <1> 	CMP	byte [DSK_STATE+eDI], 0		; NO DRIVE ?
  3345 00001C30 741D                <1> 	JZ	short DO_DET			; IF NO DRIVE ATTEMPT DETERMINE
  3346 00001C32 6689F9              <1> 	MOV	CX,DI				; CX = DRIVE NUMBER
  3347 00001C35 C0E102              <1> 	SHL	CL,2				; CL = SHIFT COUNT, A=0, B=4
  3348 00001C38 A0[686B0000]        <1> 	MOV	AL, [HF_CNTRL]			; DRIVE INFORMATION
  3349 00001C3D D2C8                <1> 	ROR	AL,CL				; TO LOW NIBBLE
  3350 00001C3F 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA	; KEEP DRIVE BITS
  3351 00001C41 80A7[696B0000]F8    <1>         AND     byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA)
  3352 00001C48 0887[696B0000]      <1> 	OR	[DSK_STATE+eDI], AL		; UPDATE DRIVE STATE
  3353                              <1> XN_OUT:
  3354 00001C4E C3                  <1> 	RETn
  3355                              <1> DO_DET:
  3356 00001C4F E897080000          <1> 	CALL	DRIVE_DET			; TRY TO DETERMINE
  3357 00001C54 C3                  <1> 	RETn
  3358                              <1> 
  3359                              <1> ;-------------------------------------------------------------------------------
  3360                              <1> ; XLAT_OLD 
  3361                              <1> ;	TRANSLATES DISKETTE STATE LOCATIONS FROM NEW
  3362                              <1> ;	ARCHITECTURE TO COMPATIBLE MODE.
  3363                              <1> ;
  3364                              <1> ; ON ENTRY:	DI = DRIVE
  3365                              <1> ;-------------------------------------------------------------------------------
  3366                              <1> XLAT_OLD:
  3367 00001C55 83FF01              <1> 	CMP	eDI,1			; VALID DRIVE ?
  3368                              <1>         ;JA     short XO_OUT            ; IF INVALID BACK
  3369                              <1>         ;ja	XO_OUT
  3370                              <1>         ; 24/12/2021
  3371 00001C58 77F4                <1> 	ja	short XN_OUT
  3372 00001C5A 80BF[696B0000]00    <1> 	CMP	byte [DSK_STATE+eDI],0	; NO DRIVE ?
  3373 00001C61 747D                <1> 	JZ	short XO_OUT		; IF NO DRIVE TRANSLATE DONE
  3374                              <1> 
  3375                              <1> ;-----	TEST FOR SAVED DRIVE INFORMATION ALREADY SET
  3376                              <1> 
  3377 00001C63 6689F9              <1> 	MOV	CX,DI			; CX = DRIVE NUMBER
  3378 00001C66 C0E102              <1> 	SHL	CL,2			; CL = SHIFT COUNT, A=0, B=4
  3379 00001C69 B402                <1> 	MOV	AH,FMT_CAPA		; LOAD MULTIPLE DATA RATE BIT MASK
  3380 00001C6B D2CC                <1> 	ROR	AH,CL			; ROTATE BY MASK
  3381 00001C6D 8425[686B0000]      <1> 	TEST	[HF_CNTRL], AH		; MULTIPLE-DATA RATE DETERMINED ?
  3382 00001C73 751C                <1> 	JNZ	short SAVE_SET		; IF SO, NO NEED TO RE-SAVE
  3383                              <1> 
  3384                              <1> ;-----	ERASE DRIVE BITS IN @HF_CNTRL FOR THIS DRIVE
  3385                              <1> 
  3386 00001C75 B407                <1> 	MOV	AH,DRV_DET+FMT_CAPA+TRK_CAPA ; MASK TO KEEP
  3387 00001C77 D2CC                <1> 	ROR	AH,CL			; FIX MASK TO KEEP
  3388 00001C79 F6D4                <1> 	NOT	AH			; TRANSLATE MASK
  3389 00001C7B 2025[686B0000]      <1> 	AND	[HF_CNTRL], AH		; KEEP BITS FROM OTHER DRIVE INTACT
  3390                              <1> 
  3391                              <1> ;-----	ACCESS CURRENT DRIVE BITS AND STORE IN @HF_CNTRL
  3392                              <1> 
  3393 00001C81 8A87[696B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; ACCESS STATE
  3394 00001C87 2407                <1> 	AND	AL,DRV_DET+FMT_CAPA+TRK_CAPA ; KEEP DRIVE BITS
  3395 00001C89 D2C8                <1> 	ROR	AL,CL			; FIX FOR THIS DRIVE
  3396 00001C8B 0805[686B0000]      <1> 	OR	[HF_CNTRL], AL		; UPDATE SAVED DRIVE STATE
  3397                              <1> 
  3398                              <1> ;-----	TRANSLATE TO COMPATIBILITY MODE
  3399                              <1> 
  3400                              <1> SAVE_SET:
  3401 00001C91 8AA7[696B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  3402 00001C97 88E7                <1> 	MOV	BH,AH			; TO BH FOR LATER
  3403 00001C99 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE
  3404 00001C9C 80FC00              <1> 	CMP	AH,RATE_500		; RATE 500 ?
  3405 00001C9F 7410                <1> 	JZ	short CHK_144		; YES 1.2/1.2 OR 1.44/1.44
  3406 00001CA1 B001                <1> 	MOV	AL,M3D1U		; AL = 360 IN 1.2 UNESTABLISHED
  3407 00001CA3 80FC40              <1> 	CMP	AH,RATE_300		; RATE 300 ?
  3408 00001CA6 7518                <1> 	JNZ	short CHK_250		; NO, 360/360, 720/720 OR 720/1.44
  3409 00001CA8 F6C720              <1> 	TEST	BH,DBL_STEP		; CHECK FOR DOUBLE STEP
  3410 00001CAB 751F                <1> 	JNZ	short TST_DET		; MUST BE 360 IN 1.2
  3411                              <1> UNKNO:
  3412 00001CAD B007                <1> 	MOV	AL,MED_UNK		; NONE OF THE ABOVE
  3413 00001CAF EB22                <1> 	JMP	SHORT AL_SET		; PROCESS COMPLETE
  3414                              <1> CHK_144:
  3415 00001CB1 E884050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  3416                              <1> 	;;20/02/2015
  3417                              <1> 	;;JC	short UNKNO		; ERROR, SET 'NONE OF ABOVE'
  3418 00001CB6 74F5                <1> 	jz	short UNKNO ;; 20/02/2015
  3419 00001CB8 3C02                <1> 	CMP	AL,2			; 1.2MB DRIVE ?
  3420 00001CBA 75F1                <1> 	JNE	short UNKNO		; NO, GO SET 'NONE OF ABOVE'
  3421 00001CBC B002                <1> 	MOV	AL,M1D1U		; AL = 1.2 IN 1.2 UNESTABLISHED
  3422 00001CBE EB0C                <1> 	JMP	SHORT TST_DET
  3423                              <1> CHK_250:
  3424 00001CC0 B000                <1> 	MOV	AL,M3D3U		; AL = 360 IN 360 UNESTABLISHED
  3425 00001CC2 80FC80              <1> 	CMP	AH,RATE_250		; RATE 250 ?
  3426 00001CC5 75E6                <1> 	JNZ	short UNKNO		; IF SO FALL IHRU
  3427 00001CC7 F6C701              <1> 	TEST	BH,TRK_CAPA		; 80 TRACK CAPABILITY ?
  3428 00001CCA 75E1                <1> 	JNZ	short UNKNO		; IF SO JUMP, FALL THRU TEST DET
  3429                              <1> TST_DET:
  3430 00001CCC F6C710              <1> 	TEST	BH,MED_DET		; DETERMINED ?
  3431 00001CCF 7402                <1> 	JZ	short AL_SET		; IF NOT THEN SET
  3432 00001CD1 0403                <1> 	ADD	AL,3			; MAKE DETERMINED/ESTABLISHED
  3433                              <1> AL_SET:
  3434 00001CD3 80A7[696B0000]F8    <1> 	AND	byte [DSK_STATE+eDI], ~(DRV_DET+FMT_CAPA+TRK_CAPA) ; CLEAR DRIVE
  3435 00001CDA 0887[696B0000]      <1> 	OR	[DSK_STATE+eDI], AL	; REPLACE WITH COMPATIBLE MODE
  3436                              <1> XO_OUT:
  3437 00001CE0 C3                  <1> 	RETn
  3438                              <1> 
  3439                              <1> ;-------------------------------------------------------------------------------
  3440                              <1> ; RD_WR_VF
  3441                              <1> ;	COMMON READ, WRITE AND VERIFY: 
  3442                              <1> ;	MAIN LOOP FOR STATE RETRIES.
  3443                              <1> ;
  3444                              <1> ; ON ENTRY:	AH = READ/WRITE/VERIFY NEC PARAMETER
  3445                              <1> ;		AL = READ/WRITE/VERIFY DMA PARAMETER
  3446                              <1> ;
  3447                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3448                              <1> ;-------------------------------------------------------------------------------
  3449                              <1> RD_WR_VF:
  3450                              <1> 	;PUSH	AX			; SAVE DMA, NEC PARAMETERS
  3451 00001CE1 50                  <1> 	push	eax ; 24/12/2021
  3452 00001CE2 E83DFFFFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH.
  3453 00001CE7 E8E9000000          <1> 	CALL	SETUP_STATE		; INITIALIZE START AND END RATE
  3454                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3455 00001CEC 58                  <1> 	pop	eax ; 24/12/2021
  3456                              <1> DO_AGAIN:
  3457                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3458 00001CED 50                  <1> 	push	eax ; 24/12/2021
  3459 00001CEE E877010000          <1> 	CALL	MED_CHANGE		; MEDIA CHANGE AND RESET IF CHANGED
  3460                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY
  3461 00001CF3 58                  <1> 	pop	eax ; 24/12/2021
  3462                              <1> 	;JC	RWV_END                 ; MEDIA CHANGE ERROR OR TIME-OUT
  3463                              <1> 	; 24/12/2021
  3464 00001CF4 7305                <1> 	jnc	short RWV
  3465 00001CF6 E9C3000000          <1> 	jmp	RWV_END
  3466                              <1> RWV:
  3467                              <1> 	;PUSH	AX			; SAVE READ/WRITE/VERIFY PARAMETER
  3468 00001CFB 50                  <1> 	push	eax ; 24/12/2021
  3469 00001CFC 8AB7[696B0000]      <1> 	MOV	DH, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3470 00001D02 80E6C0              <1> 	AND	DH,RATE_MSK		; KEEP ONLY RATE
  3471 00001D05 E830050000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL (AL)
  3472                              <1> 	;;20/02/2015
  3473                              <1> 	;;JC	short RWV_ASSUME	; ERROR IN CMOS
  3474 00001D0A 7451                <1> 	jz	short RWV_ASSUME ; 20/02/2015
  3475 00001D0C 3C01                <1> 	CMP	AL,1			; 40 TRACK DRIVE?
  3476 00001D0E 750D                <1> 	JNE	short RWV_1		; NO, BYPASS CMOS VALIDITY CHECK
  3477 00001D10 F687[696B0000]01    <1> 	TEST	byte [DSK_STATE+eDI], TRK_CAPA ; CHECK FOR 40 TRACK DRIVE
  3478 00001D17 7413                <1> 	JZ	short RWV_2		; YES, CMOS IS CORRECT
  3479 00001D19 B002                <1> 	MOV	AL,2			; CHANGE TO 1.2M
  3480 00001D1B EB0F                <1> 	JMP	SHORT RWV_2
  3481                              <1> RWV_1:
  3482 00001D1D 720D                <1> 	JB	short RWV_2		; NO DRIVE SPECIFIED, CONTINUE
  3483 00001D1F F687[696B0000]01    <1> 	TEST    byte [DSK_STATE+eDI], TRK_CAPA ; IS IT REALLY 40 TRACK?
  3484 00001D26 7504                <1> 	JNZ	short RWV_2		; NO, 80 TRACK
  3485 00001D28 B001                <1> 	MOV	AL,1			; IT IS 40 TRACK, FIX CMOS VALUE
  3486 00001D2A EB04                <1> 	jmp	short rwv_3
  3487                              <1> RWV_2:
  3488 00001D2C 08C0                <1> 	OR	AL,AL			; TEST FOR NO DRIVE
  3489 00001D2E 742D                <1> 	JZ	short RWV_ASSUME	; ASSUME TYPE, USE MAX TRACK
  3490                              <1> rwv_3:
  3491 00001D30 E87DFEFFFF          <1> 	CALL	DR_TYPE_CHECK		; RTN CS:BX = MEDIA/DRIVE PARAM TBL.
  3492 00001D35 7226                <1> 	JC	short RWV_ASSUME	; TYPE NOT IN TABLE (BAD CMOS)
  3493                              <1> 
  3494                              <1> ;-----	SEARCH FOR MEDIA/DRIVE PARAMETER TABLE
  3495                              <1> 
  3496 00001D37 57                  <1> 	PUSH	eDI			; SAVE DRIVE #
  3497 00001D38 31DB                <1> 	XOR	eBX,eBX			; BX = INDEX TO DR_TYPE TABLE
  3498 00001D3A B906000000          <1> 	MOV	eCX,DR_CNT		; CX = LOOP COUNT
  3499                              <1> RWV_DR_SEARCH:
  3500 00001D3F 8AA3[4C650000]      <1> 	MOV	AH, [DR_TYPE+eBX]	; GET DRIVE TYPE
  3501 00001D45 80E47F              <1> 	AND	AH,BIT7OFF		; MASK OUT MSB
  3502 00001D48 38E0                <1> 	CMP	AL,AH			; DRIVE TYPE MATCH?
  3503 00001D4A 750B                <1> 	JNE	short RWV_NXT_MD	; NO, CHECK NEXT DRIVE TYPE
  3504                              <1> RWV_DR_FND:
  3505 00001D4C 8BBB[4D650000]      <1> 	MOV	eDI, [DR_TYPE+eBX+1] 	; DI = MEDIA/DRIVE PARAMETER TABLE
  3506                              <1> RWV_MD_SEARH:
  3507 00001D52 3A770C              <1>         CMP     DH, [eDI+MD.RATE]       ; MATCH?
  3508 00001D55 741B                <1> 	JE	short RWV_MD_FND	; YES, GO GET 1ST SPECIFY BYTE
  3509                              <1> RWV_NXT_MD:
  3510                              <1> 	;ADD	BX,3			; CHECK NEXT DRIVE TYPE
  3511 00001D57 83C305              <1> 	add	eBX, 5
  3512 00001D5A E2E3                <1> 	LOOP	RWV_DR_SEARCH
  3513 00001D5C 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3514                              <1> 
  3515                              <1> ;-----	ASSUME PRIMARY DRIVE IS INSTALLED AS SHIPPED
  3516                              <1> 
  3517                              <1> RWV_ASSUME:
  3518 00001D5D BB[6A650000]        <1> 	MOV	eBX, MD_TBL1		; POINT TO 40 TRACK 250 KBS
  3519 00001D62 F687[696B0000]01    <1> 	TEST 	byte [DSK_STATE+eDI], TRK_CAPA ; TEST FOR 80 TRACK
  3520 00001D69 740A                <1> 	JZ	short RWV_MD_FND1	; MUST BE 40 TRACK
  3521 00001D6B BB[84650000]        <1> 	MOV	eBX, MD_TBL3		; POINT TO 80 TRACK 500 KBS
  3522 00001D70 EB03                <1> 	JMP	short RWV_MD_FND1	; GO SPECIFY PARAMTERS
  3523                              <1> 
  3524                              <1> ;-----	CS:BX POINTS TO MEDIA/DRIVE PARAMETER TABLE
  3525                              <1> 	 			
  3526                              <1> RWV_MD_FND:
  3527 00001D72 89FB                <1> 	MOV	eBX,eDI			; BX = MEDIA/DRIVE PARAMETER TABLE
  3528 00001D74 5F                  <1> 	POP	eDI			; RESTORE DRIVE #
  3529                              <1> 	
  3530                              <1> ;-----	SEND THE SPECIFY COMMAND TO THE CONTROLLER
  3531                              <1> 
  3532                              <1> RWV_MD_FND1:
  3533 00001D75 E88AFEFFFF          <1> 	CALL	SEND_SPEC_MD
  3534 00001D7A E85B010000          <1> 	CALL	CHK_LASTRATE		; ZF=1 ATTEMP RATE IS SAME AS LAST RATE
  3535 00001D7F 7405                <1> 	JZ	short RWV_DBL		; YES,SKIP SEND RATE COMMAND
  3536 00001D81 E834010000          <1> 	CALL	SEND_RATE		; SEND DATA RATE TO NEC
  3537                              <1> RWV_DBL:
  3538 00001D86 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3539 00001D87 E809040000          <1> 	CALL	SETUP_DBL		; CHECK FOR DOUBLE STEP
  3540 00001D8C 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3541 00001D8D 7222                <1> 	JC	short CHK_RET		; ERROR FROM READ ID, POSSIBLE RETRY
  3542                              <1> 	;POP	AX			; RESTORE NEC, DMA COMMAND
  3543 00001D8F 58                  <1> 	pop	eax ; 24/12/2021
  3544                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3545 00001D90 50                  <1> 	push	eax ; 24/12/2021
  3546 00001D91 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3547 00001D92 E858010000          <1> 	CALL	DMA_SETUP		; SET UP THE DMA
  3548 00001D97 5B                  <1> 	POP	eBX 
  3549                              <1> 	;POP	AX			; RESTORE NEC COMMAND
  3550 00001D98 58                  <1> 	pop	eax ; 24/12/2021
  3551 00001D99 722D                <1> 	JC	short RWV_BAC		; CHECK FOR DMA BOUNDARY ERROR
  3552                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  3553 00001D9B 50                  <1> 	push	eax ; 24/12/2021
  3554 00001D9C 53                  <1> 	PUSH	eBX			; SAVE MEDIA/DRIVE PARAM TBL ADDRESS
  3555 00001D9D E82B020000          <1> 	CALL	NEC_INIT		; INITIALIZE NEC
  3556 00001DA2 5B                  <1> 	POP	eBX			; RESTORE ADDRESS
  3557 00001DA3 720C                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3558 00001DA5 E853020000          <1> 	CALL	RWV_COM			; OP CODE COMMON TO READ/WRITE/VERIFY
  3559 00001DAA 7205                <1> 	JC	short CHK_RET		; ERROR - EXIT
  3560 00001DAC E898020000          <1> 	CALL	NEC_TERM		; TERMINATE, GET STATUS, ETC.
  3561                              <1> CHK_RET:
  3562 00001DB1 E837030000          <1> 	CALL	RETRY			; CHECK FOR, SETUP RETRY
  3563                              <1> 	;POP	AX			; RESTORE READ/WRITE/VERIFY PARAMETER
  3564 00001DB6 58                  <1> 	pop	eax ; 24/12/2021
  3565 00001DB7 7305                <1> 	JNC	short RWV_END		; CY = 0 NO RETRY
  3566 00001DB9 E92FFFFFFF          <1>         JMP     DO_AGAIN                ; CY = 1 MEANS RETRY
  3567                              <1> RWV_END:
  3568 00001DBE E8E2020000          <1> 	CALL	DSTATE			; ESTABLISH STATE IF SUCCESSFUL
  3569 00001DC3 E875030000          <1> 	CALL	NUM_TRANS		; AL = NUMBER TRANSFERRED
  3570                              <1> RWV_BAC:				; BAD DMA ERROR ENTRY
  3571                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  3572 00001DC8 50                  <1> 	push	eax ; 24/12/2021
  3573 00001DC9 E887FEFFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  3574                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  3575 00001DCE 58                  <1> 	pop	eax ; 24/12/2021
  3576 00001DCF E8A1030000          <1> 	CALL	SETUP_END		; VARIOUS CLEANUPS
  3577 00001DD4 C3                  <1> 	RETn
  3578                              <1> 
  3579                              <1> ;-------------------------------------------------------------------------------
  3580                              <1> ; SETUP_STATE:	INITIALIZES START AND END RATES.
  3581                              <1> ;-------------------------------------------------------------------------------
  3582                              <1> SETUP_STATE:
  3583 00001DD5 F687[696B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; MEDIA DETERMINED ?
  3584 00001DDC 7537                <1> 	JNZ	short J1C		; NO STATES IF DETERMINED
  3585 00001DDE 66B84000            <1>         MOV     AX,(RATE_500*256)+RATE_300  ; AH = START RATE, AL = END RATE
  3586 00001DE2 F687[696B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE ?
  3587 00001DE9 740D                <1> 	JZ	short AX_SET		; DO NOT KNOW DRIVE
  3588 00001DEB F687[696B0000]02    <1> 	TEST	byte [DSK_STATE+eDI], FMT_CAPA ; MULTI-RATE?
  3589 00001DF2 7504                <1> 	JNZ	short AX_SET		; JUMP IF YES
  3590 00001DF4 66B88080            <1>         MOV     AX,RATE_250*257         ; START A END RATE 250 FOR 360 DRIVE
  3591                              <1> AX_SET:	
  3592 00001DF8 80A7[696B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP) ; TURN OFF THE RATE
  3593 00001DFF 08A7[696B0000]      <1> 	OR	[DSK_STATE+eDI], AH	; RATE FIRST TO TRY
  3594 00001E05 8025[646B0000]F3    <1> 	AND	byte [LASTRATE], ~STRT_MSK ; ERASE LAST TO TRY RATE BITS
  3595 00001E0C C0C804              <1> 	ROR	AL,4			; TO OPERATION LAST RATE LOCATION
  3596 00001E0F 0805[646B0000]      <1> 	OR	[LASTRATE], AL		; LAST RATE
  3597                              <1> J1C:	
  3598 00001E15 C3                  <1> 	RETn
  3599                              <1> 
  3600                              <1> ;-------------------------------------------------------------------------------
  3601                              <1> ;  FMT_INIT: ESTABLISH STATE IF UNESTABLISHED AT FORMAT TIME.
  3602                              <1> ;-------------------------------------------------------------------------------
  3603                              <1> FMT_INIT:
  3604 00001E16 F687[696B0000]10    <1> 	TEST	byte [DSK_STATE+eDI], MED_DET ; IS MEDIA ESTABLISHED
  3605 00001E1D 7546                <1> 	JNZ	short F1_OUT		; IF SO RETURN
  3606 00001E1F E816040000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN AL
  3607                              <1> 	;; 20/02/2015
  3608                              <1> 	;;JC	short CL_DRV		; ERROR IN CMOS ASSUME NO DRIVE
  3609 00001E24 7440                <1> 	jz	short CL_DRV ;; 20/02/2015
  3610 00001E26 FEC8                <1> 	DEC	AL			; MAKE ZERO ORIGIN
  3611                              <1> 	;;JS	short CL_DRV		; NO DRIVE IF AL 0
  3612 00001E28 8AA7[696B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; AH = CURRENT STATE
  3613 00001E2E 80E40F              <1> 	AND	AH, ~(MED_DET+DBL_STEP+RATE_MSK) ; CLEAR
  3614 00001E31 08C0                <1> 	OR	AL,AL			; CHECK FOR 360
  3615 00001E33 7505                <1> 	JNZ	short N_360		; IF 360 WILL BE 0
  3616 00001E35 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; ESTABLISH MEDIA
  3617 00001E38 EB25                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3618                              <1> N_360:	
  3619 00001E3A FEC8                <1> 	DEC	AL			; 1.2 M DRIVE
  3620 00001E3C 7505                <1> 	JNZ	short N_12		; JUMP IF NOT
  3621                              <1> F1_RATE:
  3622 00001E3E 80CC10              <1> 	OR	AH,MED_DET+RATE_500	; SET FORMAT RATE
  3623 00001E41 EB1C                <1> 	JMP	SHORT SKP_STATE		; SKIP OTHER STATE PROCESSING
  3624                              <1> N_12:	
  3625 00001E43 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 3
  3626 00001E45 750F                <1> 	JNZ	short N_720		; JUMP IF NOT
  3627 00001E47 F6C404              <1> 	TEST	AH,DRV_DET		; IS DRIVE DETERMINED
  3628 00001E4A 7410                <1> 	JZ	short ISNT_12		; TREAT AS NON 1.2 DRIVE
  3629 00001E4C F6C402              <1> 	TEST	AH,FMT_CAPA		; IS 1.2M
  3630 00001E4F 740B                <1> 	JZ	short ISNT_12		; JUMP IF NOT
  3631 00001E51 80CC50              <1> 	OR	AH,MED_DET+RATE_300	; RATE 300
  3632 00001E54 EB09                <1> 	JMP	SHORT SKP_STATE		; CONTINUE
  3633                              <1> N_720:
  3634 00001E56 FEC8                <1> 	DEC	AL			; CHECK FOR TYPE 4
  3635 00001E58 750C                <1> 	JNZ	short CL_DRV		; NO DRIVE, CMOS BAD
  3636 00001E5A EBE2                <1> 	JMP	SHORT F1_RATE
  3637                              <1> ISNT_12: 
  3638 00001E5C 80CC90              <1> 	OR	AH,MED_DET+RATE_250	; MUST BE RATE 250
  3639                              <1> 
  3640                              <1> SKP_STATE:
  3641 00001E5F 88A7[696B0000]      <1> 	MOV	[DSK_STATE+eDI], AH	; STORE AWAY
  3642                              <1> F1_OUT:
  3643 00001E65 C3                  <1> 	RETn
  3644                              <1> CL_DRV:	
  3645 00001E66 30E4                <1> 	XOR	AH,AH			; CLEAR STATE
  3646 00001E68 EBF5                <1> 	JMP	SHORT SKP_STATE		; SAVE IT
  3647                              <1> 
  3648                              <1> ;-------------------------------------------------------------------------------
  3649                              <1> ; MED_CHANGE	
  3650                              <1> ;	CHECKS FOR MEDIA CHANGE, RESETS MEDIA CHANGE, 
  3651                              <1> ;	CHECKS MEDIA CHANGE AGAIN.
  3652                              <1> ;
  3653                              <1> ; ON EXIT:	CY = 1 MEANS MEDIA CHANGE OR TIMEOUT
  3654                              <1> ;		@DSKETTE_STATUS = ERROR CODE
  3655                              <1> ;-------------------------------------------------------------------------------
  3656                              <1> MED_CHANGE:
  3657 00001E6A E86F060000          <1> 	CALL	READ_DSKCHNG		; READ DISK CHANCE LINE STATE
  3658 00001E6F 7447                <1> 	JZ	short MC_OUT		; BYPASS HANDLING DISK CHANGE LINE
  3659 00001E71 80A7[696B0000]EF    <1> 	AND	byte [DSK_STATE+eDI], ~MED_DET ; CLEAR STATE FOR THIS DRIVE
  3660                              <1> 
  3661                              <1> ;	THIS SEQUENCE ENSURES WHENEVER A DISKETTE IS CHANGED THAT
  3662                              <1> ;	ON THE NEXT OPERATION THE REQUIRED MOTOR START UP TIME WILL
  3663                              <1> ;	BE WAITED. (DRIVE MOTOR MAY GO OFF UPON DOOR OPENING).
  3664                              <1> 
  3665 00001E78 6689F9              <1> 	MOV	CX,DI			; CL = DRIVE 0
  3666 00001E7B B001                <1> 	MOV	AL,1			; MOTOR ON BIT MASK
  3667 00001E7D D2E0                <1> 	SHL	AL,CL			; TO APPROPRIATE POSITION
  3668 00001E7F F6D0                <1> 	NOT	AL			; KEEP ALL BUT MOTOR ON
  3669 00001E81 FA                  <1> 	CLI				; NO INTERRUPTS
  3670 00001E82 2005[5A6B0000]      <1> 	AND	[MOTOR_STATUS], AL	; TURN MOTOR OFF INDICATOR
  3671 00001E88 FB                  <1> 	STI				; INTERRUPTS ENABLED
  3672 00001E89 E8FA030000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON
  3673                              <1> 
  3674                              <1> ;-----	THIS SEQUENCE OF SEEKS IS USED TO RESET DISKETTE CHANGE SIGNAL
  3675                              <1> 
  3676 00001E8E E8A4F9FFFF          <1> 	CALL	DSK_RESET		; RESET NEC
  3677 00001E93 B501                <1> 	MOV	CH,01H			; MOVE TO CYLINDER 1
  3678 00001E95 E8E8040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3679 00001E9A 30ED                <1> 	XOR	CH,CH			; MOVE TO CYLINDER 0
  3680 00001E9C E8E1040000          <1> 	CALL	SEEK			; ISSUE SEEK
  3681 00001EA1 C605[5C6B0000]06    <1> 	MOV	byte [DSKETTE_STATUS], MEDIA_CHANGE ; STORE IN STATUS
  3682                              <1> OK1:
  3683 00001EA8 E831060000          <1> 	CALL	READ_DSKCHNG		; CHECK MEDIA CHANGED AGAIN
  3684 00001EAD 7407                <1> 	JZ	short OK2		; IF ACTIVE, NO DISKETTE, TIMEOUT
  3685                              <1> OK4:
  3686 00001EAF C605[5C6B0000]80    <1> 	MOV	byte [DSKETTE_STATUS], TIME_OUT ; TIMEOUT IF DRIVE EMPTY
  3687                              <1> OK2:		
  3688 00001EB6 F9                  <1> 	STC				; MEDIA CHANGED, SET CY
  3689 00001EB7 C3                  <1> 	RETn
  3690                              <1> MC_OUT:
  3691 00001EB8 F8                  <1> 	CLC				; NO MEDIA CHANGED, CLEAR CY
  3692 00001EB9 C3                  <1> 	RETn
  3693                              <1> 
  3694                              <1> ;-------------------------------------------------------------------------------
  3695                              <1> ; SEND_RATE
  3696                              <1> ;	SENDS DATA RATE COMMAND TO NEC
  3697                              <1> ; ON ENTRY:	DI = DRIVE #
  3698                              <1> ; ON EXIT:	NONE
  3699                              <1> ; REGISTERS ALTERED: DX
  3700                              <1> ;-------------------------------------------------------------------------------
  3701                              <1> SEND_RATE:
  3702                              <1> 	;PUSH	AX			; SAVE REG.
  3703                              <1> 	; 24/12/2021
  3704 00001EBA 50                  <1> 	push	eax
  3705 00001EBB 8025[646B0000]3F    <1> 	AND	byte [LASTRATE], ~SEND_MSK ; ELSE CLEAR LAST RATE ATTEMPTED
  3706 00001EC2 8A87[696B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3707 00001EC8 24C0                <1> 	AND	AL,SEND_MSK		; KEEP ONLY RATE BITS
  3708 00001ECA 0805[646B0000]      <1> 	OR	[LASTRATE], AL		; SAVE NEW RATE FOR NEXT CHECK
  3709 00001ED0 C0C002              <1> 	ROL	AL,2			; MOVE TO BIT OUTPUT POSITIONS
  3710 00001ED3 66BAF703            <1> 	MOV	DX,03F7H		; OUTPUT NEW DATA RATE
  3711 00001ED7 EE                  <1> 	OUT	DX,AL
  3712                              <1> 	;POP	AX			; RESTORE REG.
  3713                              <1> 	; 24/12/2021
  3714 00001ED8 58                  <1> 	pop	eax
  3715 00001ED9 C3                  <1> 	RETn
  3716                              <1> 
  3717                              <1> ;-------------------------------------------------------------------------------
  3718                              <1> ; CHK_LASTRATE
  3719                              <1> ;	CHECK PREVIOUS DATE RATE SNT TO THE CONTROLLER.
  3720                              <1> ; ON ENTRY:
  3721                              <1> ;	DI = DRIVE #
  3722                              <1> ; ON EXIT:
  3723                              <1> ;	ZF =  1 DATA RATE IS THE SAME AS THE LAST RATE SENT TO NEC
  3724                              <1> ;	ZF =  0 DATA RATE IS DIFFERENT FROM LAST RATE
  3725                              <1> ; REGISTERS ALTERED: DX
  3726                              <1> ;-------------------------------------------------------------------------------
  3727                              <1> CHK_LASTRATE:
  3728                              <1> 	;PUSH	AX			; SAVE REG.
  3729                              <1> 	; 24/12/2021
  3730 00001EDA 50                  <1> 	push	eax
  3731 00001EDB 2225[646B0000]      <1> 	AND	AH, [LASTRATE]		; GET LAST DATA RATE SELECTED
  3732 00001EE1 8A87[696B0000]      <1> 	MOV	AL, [DSK_STATE+eDI]	; GET RATE STATE OF THIS DRIVE
  3733 00001EE7 6625C0C0            <1>         AND     AX, SEND_MSK*257        ; KEEP ONLY RATE BITS OF BOTH
  3734 00001EEB 38E0                <1> 	CMP	AL, AH			; COMPARE TO PREVIOUSLY TRIED
  3735                              <1> 					; ZF = 1 RATE IS THE SAME
  3736                              <1> 	;POP	AX			; RESTORE REG.
  3737                              <1> 	; 24/12/2021
  3738 00001EED 58                  <1> 	pop	eax
  3739 00001EEE C3                  <1> 	RETn
  3740                              <1> 
  3741                              <1> ;-------------------------------------------------------------------------------
  3742                              <1> ; DMA_SETUP
  3743                              <1> ;	THIS ROUTINE SETS UP THE DMA FOR READ/WRITE/VERIFY OPERATIONS.
  3744                              <1> ;
  3745                              <1> ; ON ENTRY:	AL = DMA COMMAND
  3746                              <1> ;
  3747                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3748                              <1> ;-------------------------------------------------------------------------------
  3749                              <1> 
  3750                              <1> ; SI = Head #, # of Sectors or DASD Type
  3751                              <1> 
  3752                              <1> ; 22/08/2015
  3753                              <1> ; 08/02/2015 - Protected Mode Modification
  3754                              <1> ; 06/02/2015 - 07/02/2015
  3755                              <1> ; NOTE: Buffer address must be in 1st 16MB of Physical Memory (24 bit limit).
  3756                              <1> ; (DMA Addres = Physical Address)
  3757                              <1> ; (Retro UNIX 386 v1 Kernel/System Mode Virtual Address = Physical Address)
  3758                              <1> ;
  3759                              <1> ; 04/02/2016 (clc)
  3760                              <1> ; 20/02/2015 modification (source: AWARD BIOS 1999, DMA_SETUP)
  3761                              <1> ; 16/12/2014 (IODELAY)
  3762                              <1> 
  3763                              <1> DMA_SETUP:
  3764                              <1> 
  3765                              <1> ;; 20/02/2015
  3766 00001EEF 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3767 00001EF2 F7C2000000FF        <1> 	test	edx, 0FF000000h		; 16 MB limit (22/08/2015, bugfix)
  3768 00001EF8 7569                <1> 	jnz	short dma_bnd_err_stc
  3769                              <1> 	;
  3770                              <1> 	;push	ax			; DMA command
  3771                              <1> 	; 24/12/2021
  3772 00001EFA 50                  <1> 	push	eax
  3773 00001EFB 52                  <1> 	push	edx			; *
  3774 00001EFC B203                <1> 	mov	dl, 3			; GET BYTES/SECTOR PARAMETER
  3775 00001EFE E840030000          <1> 	call	GET_PARM		; 
  3776 00001F03 88E1                <1> 	mov	cl, ah 			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3777                              <1> 	;mov	ax, si			; Sector count
  3778                              <1> 	;mov	ah, al			; AH = # OF SECTORS
  3779                              <1> 	;sub	al, al			; AL = 0, AX = # SECTORS * 256
  3780                              <1> 	;shr	ax, 1			; AX = # SECTORS * 128
  3781                              <1> 	;shl	ax, cl			; SHIFT BY PARAMETER VALUE
  3782                              <1> 	; 24/12/2021
  3783 00001F05 89F2                <1> 	mov	edx, esi
  3784 00001F07 29C0                <1> 	sub	eax, eax
  3785 00001F09 88D4                <1> 	mov	ah, dl
  3786 00001F0B D1E8                <1> 	shr	eax, 1
  3787 00001F0D D3E0                <1> 	shl	eax, cl
  3788                              <1> 	;
  3789 00001F0F 6648                <1> 	dec	ax			; -1 FOR DMA VALUE
  3790 00001F11 6689C1              <1> 	mov	cx, ax
  3791 00001F14 5A                  <1> 	pop	edx			; *
  3792                              <1> 	;pop	ax
  3793                              <1> 	; 24/12/2021
  3794 00001F15 58                  <1> 	pop	eax
  3795 00001F16 3C42                <1> 	cmp	al, 42h
  3796 00001F18 7507                <1>         jne     short NOT_VERF
  3797 00001F1A BA0000FF00          <1> 	mov	edx, 0FF0000h
  3798 00001F1F EB08                <1> 	jmp	short J33
  3799                              <1> NOT_VERF:
  3800 00001F21 6601CA              <1> 	add	dx, cx			; check for overflow
  3801 00001F24 723E                <1> 	jc	short dma_bnd_err
  3802                              <1> 	;
  3803 00001F26 6629CA              <1> 	sub	dx, cx			; Restore start address
  3804                              <1> J33:
  3805 00001F29 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3806 00001F2A E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3807                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001F2C EB00                <2>  jmp short $+2
  2150 00001F2E EB00                <2>  jmp short $+2
  3808 00001F30 E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3809 00001F32 89D0                <1> 	mov	eax,edx			; Buffer address
  3810 00001F34 E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3811                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001F36 EB00                <2>  jmp short $+2
  2150 00001F38 EB00                <2>  jmp short $+2
  3812 00001F3A 88E0                <1> 	MOV	AL,AH
  3813 00001F3C E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3814 00001F3E C1E810              <1> 	shr	eax,16
  3815                              <1> 	IODELAY				; I/O WAIT STATE
  2149 00001F41 EB00                <2>  jmp short $+2
  2150 00001F43 EB00                <2>  jmp short $+2
  3816 00001F45 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3817                              <1> 	IODELAY
  2149 00001F47 EB00                <2>  jmp short $+2
  2150 00001F49 EB00                <2>  jmp short $+2
  3818 00001F4B 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3819 00001F4E E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3820                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001F50 EB00                <2>  jmp short $+2
  2150 00001F52 EB00                <2>  jmp short $+2
  3821 00001F54 88E0                <1> 	MOV	AL,AH
  3822 00001F56 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3823                              <1> 	IODELAY
  2149 00001F58 EB00                <2>  jmp short $+2
  2150 00001F5A EB00                <2>  jmp short $+2
  3824 00001F5C FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3825 00001F5D B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3826 00001F5F E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3827                              <1> 
  3828 00001F61 F8                  <1> 	clc	; 04/02/2016
  3829 00001F62 C3                  <1> 	retn
  3830                              <1> 
  3831                              <1> dma_bnd_err_stc:
  3832 00001F63 F9                  <1> 	stc
  3833                              <1> dma_bnd_err:
  3834 00001F64 C605[5C6B0000]09    <1> 	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3835 00001F6B C3                  <1> 	RETn				; CY SET BY ABOVE IF ERROR
  3836                              <1> 
  3837                              <1> ;; 16/12/2014
  3838                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3839                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3840                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3841                              <1> ;;	IODELAY
  3842                              <1> ;; 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3843                              <1> ;;	;SIODELAY
  3844                              <1> ;;      ;CMP	AL, 42H			; DMA VERIFY COMMAND
  3845                              <1> ;;      ;JNE	short NOT_VERF		; NO
  3846                              <1> ;;      ;XOR	AX, AX			; START ADDRESS
  3847                              <1> ;;      ;JMP	SHORT J33
  3848                              <1> ;;;NOT_VERF:	
  3849                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3850                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3851                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3852                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3853                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3854                              <1> ;;	mov	eax, [ebp+4] ; 06/02/2015	
  3855                              <1> ;;	;JNC	short J33
  3856                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3857                              <1> ;;;J33:
  3858                              <1> ;;	PUSH	eAX			; SAVE START ADDRESS
  3859                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3860                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3861                              <1> ;;	IODELAY
  3862                              <1> ;;	MOV	AL,AH
  3863                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3864                              <1> ;;	shr	eax, 16	     ; 07/02/2015
  3865                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3866                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  3867                              <1> ;;	IODELAY
  3868                              <1> ;;	;AND	AL,00001111B
  3869                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  3870                              <1> ;;	;SIODELAY
  3871                              <1> ;;
  3872                              <1> ;;;----- DETERMINE COUNT
  3873                              <1> ;;	sub	eax, eax ; 08/02/2015
  3874                              <1> ;;	MOV	AX, SI			; AL =  # OF SECTORS
  3875                              <1> ;;	XCHG	AL, AH			; AH =  # OF SECTORS
  3876                              <1> ;;	SUB	AL, AL			; AL = 0, AX = # SECTORS * 256
  3877                              <1> ;;	SHR	AX, 1			; AX = # SECTORS * 128
  3878                              <1> ;;	PUSH	AX			; SAVE # OF SECTORS * 128
  3879                              <1> ;;	MOV	DL, 3			; GET BYTES/SECTOR PARAMETER
  3880                              <1> ;;	CALL	GET_PARM		; "
  3881                              <1> ;;	MOV	CL,AH			; SHIFT COUNT (0=128, 1=256, 2=512 ETC)
  3882                              <1> ;;	POP	AX			; AX = # SECTORS * 128
  3883                              <1> ;;	SHL	AX,CL			; SHIFT BY PARAMETER VALUE
  3884                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  3885                              <1> ;;	PUSH	eAX  ; 08/02/2015	; SAVE COUNT VALUE
  3886                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3887                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3888                              <1> ;;	IODELAY
  3889                              <1> ;;	MOV	AL, AH
  3890                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3891                              <1> ;;	;IODELAY
  3892                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  3893                              <1> ;;	POP	eCX  ; 08/02/2015 	; RECOVER COUNT VALUE
  3894                              <1> ;;	POP	eAX  ; 08/02/2015	; RECOVER ADDRESS VALUE
  3895                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  3896                              <1> ;;	add	ecx, eax ; 08/02/2015
  3897                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  3898                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3899                              <1> ;;	SIODELAY
  3900                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  3901                              <1> ;;	;JNC	short NO_BAD		; CHECK FOR ERROR
  3902                              <1> ;;	jc	short dma_bnd_err ; 08/02/2015
  3903                              <1> ;;	and	ecx, 0FFF00000h ; 16 MB limit
  3904                              <1> ;;	jz	short NO_BAD
  3905                              <1> ;;dma_bnd_err:
  3906                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  3907                              <1> ;;NO_BAD:
  3908                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  3909                              <1> 
  3910                              <1> ;-------------------------------------------------------------------------------
  3911                              <1> ; FMTDMA_SET
  3912                              <1> ;	THIS ROUTINE SETS UP THE DMA CONTROLLER FOR A FORMAT OPERATION.
  3913                              <1> ;
  3914                              <1> ; ON ENTRY:	NOTHING REQUIRED
  3915                              <1> ;
  3916                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  3917                              <1> ;-------------------------------------------------------------------------------
  3918                              <1> 
  3919                              <1> 	; 24/12/2021
  3920                              <1> FMTDMA_SET:
  3921                              <1> ;; 20/02/2015 modification	
  3922 00001F6C 8B5504              <1> 	mov	edx, [ebp+4] 		; Buffer address
  3923 00001F6F F7C20000F0FF        <1> 	test	edx, 0FFF00000h		; 16 MB limit
  3924 00001F75 75EC                <1> 	jnz	short dma_bnd_err_stc
  3925                              <1> 	;
  3926                              <1> 	;push	dx			; *
  3927                              <1> 	; 24/12/2021
  3928 00001F77 52                  <1> 	push	edx
  3929 00001F78 B204                <1> 	mov	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  3930 00001F7A E8C4020000          <1> 	call	GET_PARM		; "
  3931                              <1> 	;mov	al, ah			; AL = SECTORS/TRACK VALUE
  3932                              <1> 	;sub	ah, ah			; AX = SECTORS/TRACK VALUE
  3933                              <1> 	;shl	ax, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  3934                              <1> 	;dec	ax			; -1 FOR DMA VALUE
  3935                              <1> 	;mov	cx, ax
  3936                              <1> 	; 24/12/2021
  3937 00001F7F 29C9                <1> 	sub	ecx, ecx
  3938 00001F81 88E1                <1> 	mov	cl, ah			; SECTORS/TRACK VALUE
  3939 00001F83 D1E1                <1> 	shl	ecx, 1
  3940 00001F85 D1E1                <1> 	shl	ecx, 1			; cx = SEC/TRK * 4 (OFFSET C,H,R,N)
  3941 00001F87 6649                <1> 	dec	cx
  3942                              <1> 	;pop	dx			; *
  3943                              <1> 	; 24/12/2021
  3944 00001F89 5A                  <1> 	pop	edx
  3945 00001F8A 6601CA              <1> 	add	dx, cx			; check for overflow
  3946 00001F8D 72D5                <1> 	jc	short dma_bnd_err
  3947                              <1> 	;
  3948 00001F8F 6629CA              <1> 	sub	dx, cx			; Restore start address
  3949                              <1> 	;
  3950 00001F92 B04A                <1> 	MOV	AL,04AH			; WILL WRITE TO THE DISKETTE
  3951 00001F94 FA                  <1> 	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3952 00001F95 E60C                <1> 	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3953                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001F97 EB00                <2>  jmp short $+2
  2150 00001F99 EB00                <2>  jmp short $+2
  3954 00001F9B E60B                <1> 	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3955 00001F9D 89D0                <1> 	mov	eax,edx			; Buffer address
  3956 00001F9F E604                <1> 	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3957                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001FA1 EB00                <2>  jmp short $+2
  2150 00001FA3 EB00                <2>  jmp short $+2
  3958 00001FA5 88E0                <1> 	MOV	AL,AH
  3959 00001FA7 E604                <1> 	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3960 00001FA9 C1E810              <1> 	shr	eax,16
  3961                              <1> 	IODELAY				; I/O WAIT STATE
  2149 00001FAC EB00                <2>  jmp short $+2
  2150 00001FAE EB00                <2>  jmp short $+2
  3962 00001FB0 E681                <1> 	OUT	081H,AL			; OUTPUT highest BITS TO PAGE REGISTER
  3963                              <1> 	IODELAY
  2149 00001FB2 EB00                <2>  jmp short $+2
  2150 00001FB4 EB00                <2>  jmp short $+2
  3964 00001FB6 6689C8              <1> 	mov	ax,cx			; Byte count - 1
  3965 00001FB9 E605                <1> 	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  3966                              <1> 	IODELAY				; WAIT FOR I/O
  2149 00001FBB EB00                <2>  jmp short $+2
  2150 00001FBD EB00                <2>  jmp short $+2
  3967 00001FBF 88E0                <1> 	MOV	AL,AH
  3968 00001FC1 E605                <1> 	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  3969                              <1> 	IODELAY
  2149 00001FC3 EB00                <2>  jmp short $+2
  2150 00001FC5 EB00                <2>  jmp short $+2
  3970 00001FC7 FB                  <1> 	STI				; RE-ENABLE INTERRUPTS
  3971 00001FC8 B002                <1> 	MOV	AL,2			; MODE FOR 8237
  3972 00001FCA E60A                <1> 	OUT	DMA+10,AL		; INITIALIZE THE DISKETTE CHANNEL
  3973 00001FCC C3                  <1> 	retn
  3974                              <1> 
  3975                              <1> ;; 08/02/2015 - Protected Mode Modification
  3976                              <1> ;;	MOV	AL, 04AH		; WILL WRITE TO THE DISKETTE
  3977                              <1> ;;	CLI				; DISABLE INTERRUPTS DURING DMA SET-UP
  3978                              <1> ;;	OUT	DMA+12,AL		; SET THE FIRST/LA5T F/F
  3979                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3980                              <1> ;;	IODELAY
  3981                              <1> ;;	OUT	DMA+11,AL		; OUTPUT THE MODE BYTE
  3982                              <1> ;;	;MOV	AX,ES			; GET THE ES VALUE
  3983                              <1> ;;	;ROL	AX,4			; ROTATE LEFT
  3984                              <1> ;;	;MOV	CH,AL			; GET HIGHEST NIBBLE OF ES TO CH
  3985                              <1> ;;	;AND	AL,11110000B		; ZERO THE LOW NIBBLE FROM SEGMENT
  3986                              <1> ;;	;ADD	AX,[BP+2]		; TEST FOR CARRY FROM ADDITION
  3987                              <1> ;;	;JNC	short J33A
  3988                              <1> ;;	;INC	CH			; CARRY MEANS HIGH 4 BITS MUST BE INC
  3989                              <1> ;;	mov	eax, [ebp+4] ; 08/02/2015
  3990                              <1> ;;;J33A:
  3991                              <1> ;;	PUSH	eAX ; 08/02/2015	; SAVE START ADDRESS
  3992                              <1> ;;	OUT	DMA+4,AL		; OUTPUT LOW ADDRESS
  3993                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  3994                              <1> ;;	IODELAY
  3995                              <1> ;;	MOV	AL,AH
  3996                              <1> ;;	OUT	DMA+4,AL		; OUTPUT HIGH ADDRESS
  3997                              <1> ;;	shr 	eax, 16 ; 08/02/2015
  3998                              <1> ;;	;MOV	AL,CH			; GET HIGH 4 BITS
  3999                              <1> ;;	;JMP	$+2			; I/O WAIT STATE
  4000                              <1> ;;	IODELAY
  4001                              <1> ;;	;AND	AL,00001111B
  4002                              <1> ;;	OUT	081H,AL			; OUTPUT HIGH 4 BITS TO PAGE REGISTER
  4003                              <1> ;;
  4004                              <1> ;;;----- DETERMINE COUNT
  4005                              <1> ;;	sub	eax, eax ; 08/02/2015
  4006                              <1> ;;	MOV	DL, 4			; SECTORS/TRACK VALUE IN PARM TABLE
  4007                              <1> ;;	CALL	GET_PARM		; "
  4008                              <1> ;;	XCHG	AL, AH			; AL = SECTORS/TRACK VALUE
  4009                              <1> ;;	SUB	AH, AH			; AX = SECTORS/TRACK VALUE
  4010                              <1> ;;	SHL	AX, 2			; AX = SEC/TRK * 4 (OFFSET C,H,R,N)
  4011                              <1> ;;	DEC	AX			; -1 FOR DMA VALUE
  4012                              <1> ;;	PUSH	eAX 	; 08/02/2015	; SAVE # OF BYTES TO BE TRANSFERED
  4013                              <1> ;;	OUT	DMA+5,AL		; LOW BYTE OF COUNT
  4014                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4015                              <1> ;;	IODELAY
  4016                              <1> ;;	MOV	AL, AH
  4017                              <1> ;;	OUT	DMA+5,AL		; HIGH BYTE OF COUNT
  4018                              <1> ;;	STI				; RE-ENABLE INTERRUPTS
  4019                              <1> ;;	POP	eCX	; 08/02/2015	; RECOVER COUNT VALUE
  4020                              <1> ;;	POP	eAX	; 08/02/2015	; RECOVER ADDRESS VALUE
  4021                              <1> ;;	;ADD	AX, CX			; ADD, TEST FOR 64K OVERFLOW
  4022                              <1> ;;	add	ecx, eax ; 08/02/2015
  4023                              <1> ;;	MOV	AL, 2			; MODE FOR 8237
  4024                              <1> ;;	;JMP	$+2			; WAIT FOR I/O
  4025                              <1> ;;	SIODELAY
  4026                              <1> ;;	OUT	DMA+10, AL		; INITIALIZE THE DISKETTE CHANNEL
  4027                              <1> ;;	;JNC	short FMTDMA_OK		; CHECK FOR ERROR
  4028                              <1> ;;	jc	short fmtdma_bnd_err ; 08/02/2015
  4029                              <1> ;;	and	ecx, 0FFF00000h  ; 16 MB limit
  4030                              <1> ;;	jz	short FMTDMA_OK
  4031                              <1> ;;	stc	; 20/02/2015
  4032                              <1> ;;fmtdma_bnd_err:
  4033                              <1> ;;	MOV	byte [DSKETTE_STATUS], DMA_BOUNDARY ; SET ERROR
  4034                              <1> ;;FMTDMA_OK:
  4035                              <1> ;;	RETn				; CY SET BY ABOVE IF ERROR
  4036                              <1> 
  4037                              <1> ;-------------------------------------------------------------------------------
  4038                              <1> ; NEC_INIT	
  4039                              <1> ;	THIS ROUTINE SEEKS TO THE REQUESTED TRACK AND INITIALIZES
  4040                              <1> ;	THE NEC FOR THE READ/WRITE/VERIFY/FORMAT OPERATION.
  4041                              <1> ;
  4042                              <1> ; ON ENTRY:	AH = NEC COMMAND TO BE PERFORMED
  4043                              <1> ;
  4044                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4045                              <1> ;-------------------------------------------------------------------------------
  4046                              <1> NEC_INIT:
  4047                              <1> 	;PUSH	AX			; SAVE NEC COMMAND
  4048                              <1> 	; 24/12/2021
  4049 00001FCD 50                  <1> 	push	eax
  4050 00001FCE E8B5020000          <1> 	CALL	MOTOR_ON		; TURN MOTOR ON FOR SPECIFIC DRIVE
  4051                              <1> 
  4052                              <1> ;-----	DO THE SEEK OPERATION
  4053                              <1> 
  4054 00001FD3 8A6D01              <1> 	MOV	CH,[eBP+1]		; CH = TRACK #
  4055 00001FD6 E8A7030000          <1> 	CALL	SEEK			; MOVE TO CORRECT TRACK
  4056                              <1> 	;POP	AX			; RECOVER COMMAND
  4057                              <1> 	; 24/12/2021
  4058 00001FDB 58                  <1> 	pop	eax
  4059 00001FDC 721E                <1> 	JC	short ER_1		; ERROR ON SEEK
  4060 00001FDE BB[FC1F0000]        <1> 	MOV	eBX, ER_1		; LOAD ERROR ADDRESS
  4061 00001FE3 53                  <1> 	PUSH	eBX			; PUSH NEC_OUT ERROR RETURN
  4062                              <1> 
  4063                              <1> ;-----	SEND OUT THE PARAMETERS TO THE CONTROLLER
  4064                              <1> 
  4065 00001FE4 E860030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE OPERATION COMMAND
  4066 00001FE9 6689F0              <1> 	MOV	AX,SI			; AH = HEAD #
  4067 00001FEC 89FB                <1> 	MOV	eBX,eDI			; BL = DRIVE #
  4068 00001FEE C0E402              <1> 	SAL	AH,2			; MOVE IT TO BIT 2
  4069 00001FF1 80E404              <1> 	AND	AH,00000100B		; ISOLATE THAT BIT
  4070 00001FF4 08DC                <1> 	OR	AH,BL			; OR IN THE DRIVE NUMBER
  4071 00001FF6 E84E030000          <1> 	CALL	NEC_OUTPUT		; FALL THRU CY SET IF ERROR
  4072 00001FFB 5B                  <1> 	POP	eBX			; THROW AWAY ERROR RETURN
  4073                              <1> ER_1:
  4074 00001FFC C3                  <1> 	RETn
  4075                              <1> 
  4076                              <1> ;-------------------------------------------------------------------------------
  4077                              <1> ; RWV_COM
  4078                              <1> ;	THIS ROUTINE SENDS PARAMETERS TO THE NEC SPECIFIC TO THE 
  4079                              <1> ;	READ/WRITE/VERIFY OPERATIONS.
  4080                              <1> ;
  4081                              <1> ; ON ENTRY:	CS:BX = ADDRESS OF MEDIA/DRIVE PARAMETER TABLE
  4082                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4083                              <1> ;-------------------------------------------------------------------------------
  4084                              <1> RWV_COM:
  4085 00001FFD B8[48200000]        <1> 	MOV	eAX, ER_2		; LOAD ERROR ADDRESS
  4086 00002002 50                  <1> 	PUSH	eAX			; PUSH NEC_OUT ERROR RETURN
  4087 00002003 8A6501              <1> 	MOV	AH,[eBP+1]		; OUTPUT TRACK #
  4088 00002006 E83E030000          <1> 	CALL	NEC_OUTPUT
  4089 0000200B 6689F0              <1> 	MOV	AX,SI			; OUTPUT HEAD #
  4090 0000200E E836030000          <1> 	CALL	NEC_OUTPUT
  4091 00002013 8A6500              <1>         MOV     AH,[eBP]                ; OUTPUT SECTOR #
  4092 00002016 E82E030000          <1> 	CALL	NEC_OUTPUT
  4093 0000201B B203                <1> 	MOV	DL,3			; BYTES/SECTOR PARAMETER FROM BLOCK
  4094 0000201D E821020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4095 00002022 E822030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4096 00002027 B204                <1> 	MOV	DL,4			; EOT PARAMETER FROM BLOCK
  4097 00002029 E815020000          <1> 	CALL	GET_PARM 		; ... TO THE NEC
  4098 0000202E E816030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4099 00002033 8A6305              <1>         MOV     AH, [eBX+MD.GAP]        ; GET GAP LENGTH
  4100                              <1> _R15:
  4101 00002036 E80E030000          <1> 	CALL	NEC_OUTPUT
  4102 0000203B B206                <1> 	MOV	DL,6			; DTL PARAMETER PROM BLOCK
  4103 0000203D E801020000          <1> 	CALL	GET_PARM		;  TO THE NEC
  4104 00002042 E802030000          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO CONTROLLER
  4105 00002047 58                  <1> 	POP	eAX			; THROW AWAY ERROR EXIT
  4106                              <1> ER_2:
  4107 00002048 C3                  <1> 	RETn
  4108                              <1> 
  4109                              <1> ;-------------------------------------------------------------------------------
  4110                              <1> ; NEC_TERM
  4111                              <1> ;	THIS ROUTINE WAITS FOR THE OPERATION THEN ACCEPTS THE STATUS 
  4112                              <1> ;	FROM THE NEC FOR THE READ/WRITE/VERIFY/FORWAT OPERATION.
  4113                              <1> ;
  4114                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4115                              <1> ;-------------------------------------------------------------------------------
  4116                              <1> NEC_TERM:
  4117                              <1> 
  4118                              <1> ;-----	LET THE OPERATION HAPPEN
  4119                              <1> 
  4120 00002049 56                  <1> 	PUSH	eSI			; SAVE HEAD #, # OF SECTORS
  4121 0000204A E804040000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4122 0000204F 9C                  <1> 	PUSHFd	; 24/12/2021
  4123 00002050 E82E040000          <1> 	CALL	RESULTS			; GET THE NEC STATUS
  4124 00002055 724B                <1> 	JC	short SET_END_POP
  4125 00002057 9D                  <1> 	POPFd	; 24/12/2021
  4126 00002058 723E                <1> 	JC	short SET_END		; LOOK FOR ERROR
  4127                              <1> 
  4128                              <1> ;-----	CHECK THE RESULTS RETURNED BY THE CONTROLLER
  4129                              <1> 
  4130 0000205A FC                  <1> 	CLD				; SET THE CORRECT DIRECTION
  4131 0000205B BE[5D6B0000]        <1> 	MOV	eSI, NEC_STATUS		; POINT TO STATUS FIELD
  4132 00002060 AC                  <1> 	lodsb				; GET ST0
  4133 00002061 24C0                <1> 	AND	AL,11000000B		; TEST FOR NORMAL TERMINATION
  4134 00002063 7433                <1> 	JZ	short SET_END
  4135 00002065 3C40                <1> 	CMP	AL,01000000B		; TEST FOR ABNORMAL TERMINATION
  4136 00002067 7527                <1> 	JNZ	short J18		; NOT ABNORMAL, BAD NEC
  4137                              <1> 
  4138                              <1> ;-----	ABNORMAL TERMINATION, FIND OUT WHY
  4139                              <1> 
  4140 00002069 AC                  <1> 	lodsb				; GET ST1
  4141 0000206A D0E0                <1> 	SAL	AL,1			; TEST FOR EDT FOUND
  4142 0000206C B404                <1> 	MOV	AH,RECORD_NOT_FND
  4143 0000206E 7222                <1> 	JC	short J19
  4144 00002070 C0E002              <1> 	SAL	AL,2
  4145 00002073 B410                <1> 	MOV	AH,BAD_CRC
  4146 00002075 721B                <1> 	JC	short J19
  4147 00002077 D0E0                <1> 	SAL	AL,1			; TEST FOR DMA OVERRUN
  4148 00002079 B408                <1> 	MOV	AH,BAD_DMA
  4149 0000207B 7215                <1> 	JC	short J19
  4150 0000207D C0E002              <1> 	SAL	AL,2			; TEST FOR RECORD NOT FOUND
  4151 00002080 B404                <1> 	MOV	AH,RECORD_NOT_FND
  4152 00002082 720E                <1> 	JC	short J19
  4153 00002084 D0E0                <1> 	SAL	AL,1
  4154 00002086 B403                <1> 	MOV	AH,WRITE_PROTECT	; TEST FOR WRITE_PROTECT
  4155 00002088 7208                <1> 	JC	short J19
  4156 0000208A D0E0                <1> 	SAL	AL,1			; TEST MISSING ADDRESS MARK
  4157 0000208C B402                <1> 	MOV	AH,BAD_ADDR_MARK
  4158 0000208E 7202                <1> 	JC	short J19
  4159                              <1> 
  4160                              <1> ;----- 	NEC MUST HAVE FAILED
  4161                              <1> J18:
  4162 00002090 B420                <1> 	MOV	AH,BAD_NEC
  4163                              <1> J19:
  4164 00002092 0825[5C6B0000]      <1> 	OR	[DSKETTE_STATUS],AH
  4165                              <1> SET_END:
  4166 00002098 803D[5C6B0000]01    <1> 	CMP	byte [DSKETTE_STATUS],1 ; SET ERROR CONDITION
  4167 0000209F F5                  <1> 	CMC
  4168 000020A0 5E                  <1> 	POP	eSI
  4169 000020A1 C3                  <1> 	RETn				; RESTORE HEAD #, # OF SECTORS
  4170                              <1> 
  4171                              <1> SET_END_POP:
  4172 000020A2 9D                  <1> 	POPFd	; 24/12/2021
  4173 000020A3 EBF3                <1> 	JMP	SHORT SET_END
  4174                              <1> 
  4175                              <1> ;-------------------------------------------------------------------------------
  4176                              <1> ; DSTATE:	ESTABLISH STATE UPON SUCCESSFUL OPERATION.
  4177                              <1> ;-------------------------------------------------------------------------------
  4178                              <1> DSTATE:
  4179 000020A5 803D[5C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4180 000020AC 753E                <1> 	JNZ	short SETBAC		    ; IF ERROR JUMP
  4181 000020AE 808F[696B0000]10    <1> 	OR	byte [DSK_STATE+eDI],MED_DET ; NO ERROR, MARK MEDIA AS DETERMINED
  4182 000020B5 F687[696B0000]04    <1> 	TEST	byte [DSK_STATE+eDI],DRV_DET ; DRIVE DETERMINED ?
  4183 000020BC 752E                <1> 	JNZ	short SETBAC		; IF DETERMINED NO TRY TO DETERMINE
  4184 000020BE 8A87[696B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4185 000020C4 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4186 000020C6 3C80                <1> 	CMP	AL,RATE_250		; RATE 250 ?
  4187 000020C8 751B                <1> 	JNE	short M_12		; NO, MUST BE 1.2M OR 1.44M DRIVE
  4188                              <1> 
  4189                              <1> ;----- 	CHECK IF IT IS 1.44M
  4190                              <1> 
  4191 000020CA E86B010000          <1> 	CALL	CMOS_TYPE		; RETURN DRIVE TYPE IN (AL)
  4192                              <1> 	;;20/02/2015
  4193                              <1> 	;;JC	short M_12		; CMOS BAD
  4194 000020CF 7414                <1> 	jz	short M_12 ;; 20/02/2015
  4195 000020D1 3C04                <1> 	CMP	AL, 4			; 1.44MB DRIVE ?
  4196 000020D3 7410                <1> 	JE	short M_12		; YES
  4197                              <1> M_720:
  4198 000020D5 80A7[696B0000]FD    <1> 	AND	byte [DSK_STATE+eDI], ~FMT_CAPA ; TURN OFF FORMAT CAPABILITY
  4199 000020DC 808F[696B0000]04    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET  ; MARK DRIVE DETERMINED
  4200 000020E3 EB07                <1> 	JMP	SHORT SETBAC		; BACK
  4201                              <1> M_12:	
  4202 000020E5 808F[696B0000]06    <1> 	OR	byte [DSK_STATE+eDI],DRV_DET+FMT_CAPA 
  4203                              <1> 					; TURN ON DETERMINED & FMT CAPA
  4204                              <1> SETBAC:
  4205 000020EC C3                  <1> 	RETn
  4206                              <1> 
  4207                              <1> ;-------------------------------------------------------------------------------
  4208                              <1> ; RETRY	
  4209                              <1> ;	DETERMINES WHETHER A RETRY IS NECESSARY. 
  4210                              <1> ;	IF RETRY IS REQUIRED THEN STATE INFORMATION IS UPDATED FOR RETRY.
  4211                              <1> ;
  4212                              <1> ; ON EXIT:	CY = 1 FOR RETRY, CY = 0 FOR NO RETRY
  4213                              <1> ;-------------------------------------------------------------------------------
  4214                              <1> RETRY:
  4215 000020ED 803D[5C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; GET STATUS OF OPERATION
  4216 000020F4 7445                <1> 	JZ	short NO_RETRY		; SUCCESSFUL OPERATION
  4217 000020F6 803D[5C6B0000]80    <1> 	CMP	byte [DSKETTE_STATUS],TIME_OUT ; IF TIME OUT NO RETRY
  4218 000020FD 743C                <1> 	JZ	short NO_RETRY
  4219 000020FF 8AA7[696B0000]      <1> 	MOV	AH,[DSK_STATE+eDI]	; GET MEDIA STATE OF DRIVE
  4220 00002105 F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED/DETERMINED ?
  4221 00002108 7531                <1> 	JNZ	short NO_RETRY		; IF ESTABLISHED STATE THEN TRUE ERROR
  4222 0000210A 80E4C0              <1> 	AND	AH,RATE_MSK		; ISOLATE RATE
  4223 0000210D 8A2D[646B0000]      <1> 	MOV	CH,[LASTRATE]		; GET START OPERATION STATE
  4224 00002113 C0C504              <1> 	ROL	CH,4			; TO CORRESPONDING BITS
  4225 00002116 80E5C0              <1> 	AND	CH,RATE_MSK		; ISOLATE RATE BITS
  4226 00002119 38E5                <1> 	CMP	CH,AH			; ALL RATES TRIED
  4227 0000211B 741E                <1> 	JE	short NO_RETRY		; IF YES, THEN TRUE ERROR
  4228                              <1> 
  4229                              <1> ;	SETUP STATE INDICATOR FOR RETRY ATTEMPT TO NEXT RATE
  4230                              <1> ;	 00000000B (500) -> 10000000B	(250)
  4231                              <1> ;	 10000000B (250) -> 01000000B	(300)
  4232                              <1> ;	 01000000B (300) -> 00000000B	(500)
  4233                              <1> 
  4234 0000211D 80FC01              <1> 	CMP	AH,RATE_500+1		; SET CY FOR RATE 500
  4235 00002120 D0DC                <1> 	RCR	AH,1			; TO NEXT STATE
  4236 00002122 80E4C0              <1> 	AND	AH,RATE_MSK		; KEEP ONLY RATE BITS
  4237 00002125 80A7[696B0000]1F    <1> 	AND	byte [DSK_STATE+eDI], ~(RATE_MSK+DBL_STEP)
  4238                              <1> 					; RATE, DBL STEP OFF
  4239 0000212C 08A7[696B0000]      <1> 	OR	[DSK_STATE+eDI],AH	; TURN ON NEW RATE
  4240 00002132 C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; RESET STATUS FOR RETRY
  4241 00002139 F9                  <1> 	STC				; SET CARRY FOR RETRY
  4242 0000213A C3                  <1> 	RETn				; RETRY RETURN
  4243                              <1> 
  4244                              <1> NO_RETRY:
  4245 0000213B F8                  <1> 	CLC				; CLEAR CARRY NO RETRY
  4246 0000213C C3                  <1> 	RETn				; NO RETRY RETURN
  4247                              <1> 
  4248                              <1> ;-------------------------------------------------------------------------------
  4249                              <1> ; NUM_TRANS
  4250                              <1> ;	THIS ROUTINE CALCULATES THE NUMBER OF SECTORS THAT WERE
  4251                              <1> ;	ACTUALLY TRANSFERRED TO/FROM THE DISKETTE.
  4252                              <1> ;
  4253                              <1> ; ON ENTRY:	[BP+1] = TRACK
  4254                              <1> ;		SI-HI  = HEAD
  4255                              <1> ;		[BP]   = START SECTOR
  4256                              <1> ;
  4257                              <1> ; ON EXIT:	AL = NUMBER ACTUALLY TRANSFERRED
  4258                              <1> ;-------------------------------------------------------------------------------
  4259                              <1> NUM_TRANS:
  4260 0000213D 30C0                <1> 	XOR	AL,AL			; CLEAR FOR ERROR
  4261 0000213F 803D[5C6B0000]00    <1> 	CMP	byte [DSKETTE_STATUS],0	; CHECK FOR ERROR
  4262                              <1> 	; 24/12/2021
  4263 00002146 752C                <1> 	JNZ	short NT_OUT		; IF ERROR 0 TRANSFERRED
  4264 00002148 B204                <1> 	MOV	DL,4			; SECTORS/TRACK OFFSET TO DL
  4265 0000214A E8F4000000          <1> 	CALL	GET_PARM		; AH = SECTORS/TRACK
  4266 0000214F 8A1D[626B0000]      <1> 	MOV	BL, [NEC_STATUS+5]	; GET ENDING SECTOR
  4267 00002155 6689F1              <1> 	MOV	CX,SI			; CH = HEAD # STARTED
  4268 00002158 3A2D[616B0000]      <1> 	CMP	CH, [NEC_STATUS+4]	; GET HEAD ENDED UP ON
  4269 0000215E 750D                <1> 	JNZ	DIF_HD			; IF ON SAME HEAD, THEN NO ADJUST
  4270 00002160 8A2D[606B0000]      <1> 	MOV	CH, [NEC_STATUS+3]	; GET TRACK ENDED UP ON
  4271 00002166 3A6D01              <1> 	CMP	CH,[eBP+1]		; IS IT ASKED FOR TRACK
  4272 00002169 7404                <1> 	JZ	short SAME_TRK		; IF SAME TRACK NO INCREASE
  4273 0000216B 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4274                              <1> DIF_HD:
  4275 0000216D 00E3                <1> 	ADD	BL,AH			; ADD SECTORS/TRACK
  4276                              <1> SAME_TRK:
  4277 0000216F 2A5D00              <1> 	SUB	BL,[eBP]		; SUBTRACT START FROM END
  4278 00002172 88D8                <1> 	MOV	AL,BL			; TO AL
  4279                              <1> NT_OUT:
  4280 00002174 C3                  <1> 	RETn
  4281                              <1> 
  4282                              <1> ;-------------------------------------------------------------------------------
  4283                              <1> ; SETUP_END
  4284                              <1> ;	RESTORES @MOTOR_COUNT TO PARAMETER PROVIDED IN TABLE 
  4285                              <1> ;	AND LOADS @DSKETTE_STATUS TO AH, AND SETS CY.
  4286                              <1> ;
  4287                              <1> ; ON EXIT:
  4288                              <1> ;	AH, @DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4289                              <1> ;-------------------------------------------------------------------------------
  4290                              <1> SETUP_END:
  4291 00002175 B202                <1> 	MOV	DL,2			; GET THE MOTOR WAIT PARAMETER
  4292                              <1> 	;PUSH	AX			; SAVE NUMBER TRANSFERRED
  4293 00002177 50                  <1> 	push	eax ; 24/12/2021
  4294 00002178 E8C6000000          <1> 	CALL	GET_PARM
  4295 0000217D 8825[5B6B0000]      <1> 	MOV	[MOTOR_COUNT],AH	; STORE UPON RETURN
  4296                              <1> 	;POP	AX			; RESTORE NUMBER TRANSFERRED
  4297 00002183 58                  <1> 	pop	eax ; 24/12/2021
  4298 00002184 8A25[5C6B0000]      <1> 	MOV	AH, [DSKETTE_STATUS]	; GET STATUS OF OPERATION
  4299 0000218A 08E4                <1> 	OR	AH,AH			; CHECK FOR ERROR
  4300 0000218C 7402                <1> 	JZ	short NUN_ERR			; NO ERROR
  4301 0000218E 30C0                <1> 	XOR	AL,AL			; CLEAR NUMBER RETURNED
  4302                              <1> NUN_ERR: 
  4303 00002190 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  4304 00002193 F5                  <1> 	CMC				; SUCCESS OR FAILURE
  4305 00002194 C3                  <1> 	RETn
  4306                              <1> 
  4307                              <1> ;-------------------------------------------------------------------------------
  4308                              <1> ; SETUP_DBL
  4309                              <1> ;	CHECK DOUBLE STEP.
  4310                              <1> ;
  4311                              <1> ; ON ENTRY :	DI = DRIVE
  4312                              <1> ;
  4313                              <1> ; ON EXIT :	CY = 1 MEANS ERROR
  4314                              <1> ;-------------------------------------------------------------------------------
  4315                              <1> SETUP_DBL:
  4316 00002195 8AA7[696B0000]      <1> 	MOV	AH, [DSK_STATE+eDI]	; ACCESS STATE
  4317 0000219B F6C410              <1> 	TEST	AH,MED_DET		; ESTABLISHED STATE ?
  4318 0000219E 757A                <1> 	JNZ	short NO_DBL			; IF ESTABLISHED THEN DOUBLE DONE
  4319                              <1> 
  4320                              <1> ;-----	CHECK FOR TRACK 0 TO SPEED UP ACKNOWLEDGE OF UNFORMATTED DISKETTE
  4321                              <1> 
  4322 000021A0 C605[596B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; SET RECALIBRATE REQUIRED ON ALL DRIVES
  4323 000021A7 E8DC000000          <1> 	CALL	MOTOR_ON		; ENSURE MOTOR STAY ON
  4324 000021AC B500                <1> 	MOV	CH,0			; LOAD TRACK 0
  4325 000021AE E8CF010000          <1> 	CALL	SEEK			; SEEK TO TRACK 0
  4326 000021B3 E864000000          <1> 	CALL	READ_ID			; READ ID FUNCTION
  4327 000021B8 7245                <1> 	JC	short SD_ERR		; IF ERROR NO TRACK 0
  4328                              <1> 
  4329                              <1> ;-----	INITIALIZE START AND MAX TRACKS (TIMES 2 FOR BOTH HEADS)
  4330                              <1> 
  4331 000021BA 66B95004            <1> 	MOV	CX,0450H 		; START, MAX TRACKS
  4332 000021BE F687[696B0000]01    <1> 	TEST	byte [DSK_STATE+eDI],TRK_CAPA ; TEST FOR 80 TRACK CAPABILITY
  4333 000021C5 7402                <1> 	JZ	short CNT_OK		; IF NOT COUNT IS SETUP
  4334 000021C7 B1A0                <1> 	MOV	CL,0A0H			; MAXIMUM TRACK 1.2 MB
  4335                              <1> 
  4336                              <1> ;	ATTEMPT READ ID OF ALL TRACKS, ALL HEADS UNTIL SUCCESS; UPON SUCCESS,
  4337                              <1> ;	MUST SEE IF ASKED FOR TRACK IN SINGLE STEP MODE = TRACK ID READ; IF NOT
  4338                              <1> ;	THEN SET DOUBLE STEP ON.
  4339                              <1> 
  4340                              <1> CNT_OK:
  4341 000021C9 C605[5B6B0000]FF    <1>         MOV     byte [MOTOR_COUNT], 0FFH ; ENSURE MOTOR STAYS ON FOR OPERATION 
  4342                              <1> 	;PUSH	CX			; SAVE TRACK, COUNT
  4343                              <1> 	; 24/12/2021
  4344 000021D0 51                  <1> 	push	ecx
  4345 000021D1 C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR STATUS, EXPECT ERRORS
  4346 000021D8 6631C0              <1> 	XOR	AX,AX			; CLEAR AX
  4347 000021DB D0ED                <1> 	SHR	CH,1			; HALVE TRACK, CY = HEAD
  4348 000021DD C0D003              <1> 	RCL	AL,3			; AX = HEAD IN CORRECT BIT
  4349                              <1> 	;PUSH	AX			; SAVE HEAD
  4350                              <1> 	; 24/12/2021
  4351 000021E0 50                  <1> 	push	eax
  4352 000021E1 E89C010000          <1> 	CALL	SEEK			; SEEK TO TRACK
  4353                              <1> 	;POP	AX			; RESTORE HEAD
  4354                              <1> 	; 24/12/2021
  4355 000021E6 58                  <1> 	pop	eax
  4356 000021E7 6609C7              <1> 	OR	DI,AX			; DI = HEAD OR'ED DRIVE
  4357 000021EA E82D000000          <1> 	CALL	READ_ID			; READ ID HEAD 0
  4358 000021EF 9C                  <1> 	PUSHF				; SAVE RETURN FROM READ_ID
  4359 000021F0 6681E7FB00          <1> 	AND	DI,11111011B		; TURN OFF HEAD 1 BIT
  4360 000021F5 9D                  <1> 	POPF				; RESTORE ERROR RETURN
  4361                              <1> 	;POP	CX			; RESTORE COUNT
  4362                              <1> 	; 24/12/2021
  4363 000021F6 59                  <1> 	pop	ecx
  4364 000021F7 7308                <1> 	JNC	short DO_CHK		; IF OK, ASKED = RETURNED TRACK ?
  4365 000021F9 FEC5                <1> 	INC	CH			; INC FOR NEXT TRACK
  4366 000021FB 38CD                <1> 	CMP	CH,CL			; REACHED MAXIMUM YET
  4367 000021FD 75CA                <1> 	JNZ	short CNT_OK		; CONTINUE TILL ALL TRIED
  4368                              <1> 
  4369                              <1> ;-----	FALL THRU, READ ID FAILED FOR ALL TRACKS
  4370                              <1> 
  4371                              <1> SD_ERR:	
  4372 000021FF F9                  <1> 	STC				; SET CARRY FOR ERROR
  4373 00002200 C3                  <1> 	RETn				; SETUP_DBL ERROR EXIT
  4374                              <1> 
  4375                              <1> DO_CHK:
  4376 00002201 8A0D[606B0000]      <1> 	MOV	CL, [NEC_STATUS+3]	; LOAD RETURNED TRACK
  4377 00002207 888F[6D6B0000]      <1> 	MOV	[DSK_TRK+eDI], CL	; STORE TRACK NUMBER
  4378 0000220D D0ED                <1> 	SHR	CH,1			; HALVE TRACK
  4379 0000220F 38CD                <1> 	CMP	CH,CL			; IS IT THE SAME AS ASKED FOR TRACK
  4380 00002211 7407                <1> 	JZ	short NO_DBL		; IF SAME THEN NO DOUBLE STEP
  4381 00002213 808F[696B0000]20    <1> 	OR	byte [DSK_STATE+eDI],DBL_STEP ; TURN ON DOUBLE STEP REQUIRED
  4382                              <1> NO_DBL:
  4383 0000221A F8                  <1> 	CLC				; CLEAR ERROR FLAG
  4384 0000221B C3                  <1> 	RETn
  4385                              <1> 
  4386                              <1> ;-------------------------------------------------------------------------------
  4387                              <1> ; READ_ID
  4388                              <1> ;	READ ID FUNCTION.
  4389                              <1> ;
  4390                              <1> ; ON ENTRY:	DI : BIT 2 = HEAD; BITS 1,0 = DRIVE
  4391                              <1> ;
  4392                              <1> ; ON EXIT: 	DI : BIT 2 IS RESET, BITS 1,0 = DRIVE
  4393                              <1> ;		@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION
  4394                              <1> ;-------------------------------------------------------------------------------
  4395                              <1> READ_ID:
  4396 0000221C B8[39220000]        <1> 	MOV	eAX, ER_3		; MOVE NEC OUTPUT ERROR ADDRESS
  4397 00002221 50                  <1> 	PUSH	eAX
  4398 00002222 B44A                <1> 	MOV	AH,4AH			; READ ID COMMAND
  4399 00002224 E820010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4400 00002229 6689F8              <1> 	MOV	AX,DI			; DRIVE # TO AH, HEAD 0
  4401 0000222C 88C4                <1> 	MOV	AH,AL
  4402 0000222E E816010000          <1> 	CALL	NEC_OUTPUT		; TO CONTROLLER
  4403 00002233 E811FEFFFF          <1> 	CALL	NEC_TERM		; WAIT FOR OPERATION, GET STATUS
  4404 00002238 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  4405                              <1> ER_3:
  4406 00002239 C3                  <1> 	RETn
  4407                              <1> 
  4408                              <1> ;-------------------------------------------------------------------------------
  4409                              <1> ; CMOS_TYPE
  4410                              <1> ;	RETURNS DISKETTE TYPE FROM CMOS
  4411                              <1> ;
  4412                              <1> ; ON ENTRY:	DI = DRIVE #
  4413                              <1> ;
  4414                              <1> ; ON EXIT:	AL = TYPE; CY REFLECTS STATUS
  4415                              <1> ;-------------------------------------------------------------------------------
  4416                              <1> 
  4417                              <1> CMOS_TYPE: ; 11/12/2014
  4418 0000223A 8A87[CE650000]      <1> 	mov	al, [eDI+fd0_type]
  4419 00002240 20C0                <1> 	and 	al, al ; 18/12/2014
  4420 00002242 C3                  <1> 	retn
  4421                              <1> 
  4422                              <1> ;CMOS_TYPE:
  4423                              <1> ;	MOV	AL, CMOS_DIAG		; CMOS DIAGNOSTIC STATUS BYTE ADDRESS
  4424                              <1> ;	CALL	CMOS_READ		; GET CMOS STATUS
  4425                              <1> ;	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY GOOD AND CHECKSUM VALID
  4426                              <1> ;	STC				; SET CY = 1 INDICATING ERROR FOR RETURN
  4427                              <1> ;	JNZ	short BAD_CM		; ERROR IF EITHER BIT ON
  4428                              <1> ;	MOV	AL,CMOS_DISKETTE	; ADDRESS OF DISKETTE BYTE IN CMOS
  4429                              <1> ;	CALL	CMOS_READ		; GET DISKETTE BYTE
  4430                              <1> ;	OR	DI,DI			; SEE WHICH DRIVE IN QUESTION
  4431                              <1> ;	JNZ	short TB		; IF DRIVE 1, DATA IN LOW NIBBLE
  4432                              <1> ;	ROR	AL,4			; EXCHANGE NIBBLES IF SECOND DRIVE
  4433                              <1> ;TB:
  4434                              <1> ;	AND	AL,0FH			; KEEP ONLY DRIVE DATA, RESET CY, 0
  4435                              <1> ;BAD_CM:
  4436                              <1> ;	RETn				; CY, STATUS OF READ
  4437                              <1> 
  4438                              <1> ;-------------------------------------------------------------------------------
  4439                              <1> ; GET_PARM
  4440                              <1> ;	THIS ROUTINE FETCHES THE INDEXED POINTER FROM THE DISK_BASE
  4441                              <1> ;	BLOCK POINTED TO BY THE DATA VARIABLE @DISK_POINTER. A BYTE FROM
  4442                              <1> ;	THAT TABLE IS THEN MOVED INTO AH, THE INDEX OF THAT BYTE BEING
  4443                              <1> ;	THE PARAMETER IN DL.
  4444                              <1> ;
  4445                              <1> ; ON ENTRY:	DL = INDEX OF BYTE TO BE FETCHED
  4446                              <1> ;
  4447                              <1> ; ON EXIT:	AH = THAT BYTE FROM BLOCK
  4448                              <1> ;		AL,DH DESTROYED
  4449                              <1> ;-------------------------------------------------------------------------------
  4450                              <1> GET_PARM:
  4451                              <1> 	;PUSH	DS
  4452 00002243 56                  <1> 	PUSH	eSI
  4453                              <1>     	;SUB	AX,AX			; DS = 0, BIOS DATA AREA
  4454                              <1>     	;MOV	DS,AX
  4455                              <1> 	;;mov	ax, cs
  4456                              <1> 	;;mov	ds, ax
  4457                              <1> 	; 08/02/2015 (protected mode modifications, bx -> ebx)
  4458 00002244 87D3                <1> 	XCHG	eDX,eBX			; BL = INDEX
  4459                              <1> 	;SUB	BH,BH			; BX = INDEX
  4460 00002246 81E3FF000000        <1> 	and	ebx, 0FFh
  4461                              <1>     	;LDS	SI, [DISK_POINTER]	; POINT TO BLOCK
  4462                              <1> 	;
  4463                              <1> 	; 17/12/2014
  4464 0000224C 66A1[C1650000]      <1> 	mov	ax, [cfd] ; current (AL) and previous fd (AH)
  4465 00002252 38E0                <1> 	cmp	al, ah
  4466 00002254 7425                <1> 	je	short gpndc
  4467 00002256 A2[C2650000]        <1> 	mov	[pfd], al ; current drive -> previous drive
  4468 0000225B 53                  <1> 	push	ebx ; 08/02/2015
  4469 0000225C 88C3                <1> 	mov	bl, al 
  4470                              <1> 	; 11/12/2014
  4471 0000225E 8A83[CE650000]      <1> 	mov	al, [eBX+fd0_type]	; Drive type (0,1,2,3,4)
  4472                              <1> 	; 18/12/2014
  4473 00002264 20C0                <1> 	and	al, al
  4474 00002266 7507                <1> 	jnz	short gpdtc
  4475 00002268 BB[AB650000]        <1> 	mov	ebx, MD_TBL6		; 1.44 MB param. tbl. (default)
  4476 0000226D EB05                <1>         jmp     short gpdpu
  4477                              <1> gpdtc:	
  4478 0000226F E83EF9FFFF          <1> 	call	DR_TYPE_CHECK
  4479                              <1> 	; cf = 1 -> eBX points to 1.44MB fd parameter table (default)
  4480                              <1> gpdpu:
  4481 00002274 891D[48650000]      <1> 	mov	[DISK_POINTER], ebx
  4482 0000227A 5B                  <1> 	pop	ebx
  4483                              <1> gpndc:
  4484 0000227B 8B35[48650000]      <1> 	mov	esi, [DISK_POINTER] ; 08/02/2015, si -> esi
  4485 00002281 8A241E              <1> 	MOV	AH, [eSI+eBX]		; GET THE WORD
  4486 00002284 87D3                <1> 	XCHG	eDX,eBX			; RESTORE BX
  4487 00002286 5E                  <1> 	POP	eSI
  4488                              <1> 	;POP	DS
  4489 00002287 C3                  <1> 	RETn
  4490                              <1> 
  4491                              <1> ;-------------------------------------------------------------------------------
  4492                              <1> ; MOTOR_ON
  4493                              <1> ;	TURN MOTOR ON AND WAIT FOR MOTOR START UP TIME. THE @MOTOR_COUNT
  4494                              <1> ;	IS REPLACED WITH A SUFFICIENTLY HIGH NUMBER (0FFH) TO ENSURE
  4495                              <1> ;	THAT THE MOTOR DOES NOT GO OFF DURING THE OPERATION. IF THE
  4496                              <1> ;	MOTOR NEEDED TO BE TURNED ON, THE MULTI-TASKING HOOK FUNCTION
  4497                              <1> ;	(AX=90FDH, INT 15) IS CALLED TELLING THE OPERATING SYSTEM
  4498                              <1> ;	THAT THE BIOS IS ABOUT TO WAIT FOR MOTOR START UP. IF THIS
  4499                              <1> ;	FUNCTION RETURNS WITH CY = 1, IT MEANS THAT THE MINIMUM WAIT
  4500                              <1> ;	HAS BEEN COMPLETED. AT THIS POINT A CHECK IS MADE TO ENSURE
  4501                              <1> ;	THAT THE MOTOR WASN'T TURNED OFF BY THE TIMER. IF THE HOOK DID
  4502                              <1> ;	NOT WAIT, THE WAIT FUNCTION (AH=086H) IS CALLED TO WAIT THE
  4503                              <1> ;	PRESCRIBED AMOUNT OF TIME. IF THE CARRY FLAG IS SET ON RETURN,
  4504                              <1> ;	IT MEANS THAT THE FUNCTION IS IN USE AND DID NOT PERFORM THE
  4505                              <1> ;	WAIT. A TIMER 1 WAIT LOOP WILL THEN DO THE WAIT.
  4506                              <1> ;
  4507                              <1> ; ON ENTRY:	DI = DRIVE #
  4508                              <1> ; ON EXIT:	AX,CX,DX DESTROYED
  4509                              <1> ;-------------------------------------------------------------------------------
  4510                              <1> MOTOR_ON:
  4511 00002288 53                  <1> 	PUSH	eBX			; SAVE REG.
  4512 00002289 E82A000000          <1> 	CALL	TURN_ON			; TURN ON MOTOR
  4513 0000228E 7226                <1> 	JC	short MOT_IS_ON		; IF CY=1 NO WAIT
  4514 00002290 E8C0F9FFFF          <1> 	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  4515 00002295 E88AF9FFFF          <1> 	CALL	XLAT_NEW		; TRANSLATE STATE TO PRESENT ARCH,
  4516                              <1> 	;CALL	TURN_ON 		; CHECK AGAIN IF MOTOR ON
  4517                              <1> 	;JC	MOT_IS_ON		; IF NO WAIT MEANS IT IS ON
  4518                              <1> M_WAIT:
  4519 0000229A B20A                <1> 	MOV	DL,10			; GET THE MOTOR WAIT PARAMETER
  4520 0000229C E8A2FFFFFF          <1> 	CALL	GET_PARM
  4521                              <1> 	;MOV	AL,AH			; AL = MOTOR WAIT PARAMETER
  4522                              <1> 	;XOR	AH,AH			; AX = MOTOR WAIT PARAMETER
  4523                              <1> 	;CMP	AL,8			; SEE IF AT LEAST A SECOND IS SPECIFIED
  4524 000022A1 80FC08              <1> 	cmp	ah, 8
  4525                              <1> 	;JAE	short GP2		; IF YES, CONTINUE
  4526 000022A4 7702                <1> 	ja	short J13
  4527                              <1> 	;MOV	AL,8			; ONE SECOND WAIT FOR MOTOR START UP
  4528 000022A6 B408                <1> 	mov	ah, 8
  4529                              <1> 
  4530                              <1> ;-----	AS CONTAINS NUMBER OF 1/8 SECONDS (125000 MICROSECONDS) TO WAIT
  4531                              <1> GP2:	
  4532                              <1> ;----- 	FOLLOWING LOOPS REQUIRED WHEN RTC WAIT FUNCTION IS ALREADY IN USE
  4533                              <1> J13:					; WAIT FOR 1/8 SECOND PER (AL)
  4534 000022A8 B95E200000          <1> 	MOV	eCX,8286		; COUNT FOR 1/8 SECOND AT 15.085737 US
  4535 000022AD E80BF2FFFF          <1> 	CALL	WAITF			; GO TO FIXED WAIT ROUTINE
  4536                              <1> 	;DEC	AL			; DECREMENT TIME VALUE
  4537 000022B2 FECC                <1> 	dec	ah
  4538 000022B4 75F2                <1> 	JNZ	short J13		; ARE WE DONE YET
  4539                              <1> MOT_IS_ON:
  4540 000022B6 5B                  <1> 	POP	eBX			; RESTORE REG.
  4541 000022B7 C3                  <1> 	RETn
  4542                              <1> 
  4543                              <1> ;-------------------------------------------------------------------------------
  4544                              <1> ; TURN_ON
  4545                              <1> ;	TURN MOTOR ON AND RETURN WAIT STATE.
  4546                              <1> ;
  4547                              <1> ; ON ENTRY:	DI = DRIVE #
  4548                              <1> ;
  4549                              <1> ; ON EXIT:	CY = 0 MEANS WAIT REQUIRED
  4550                              <1> ;		CY = 1 MEANS NO WAIT REQUIRED
  4551                              <1> ;		AX,BX,CX,DX DESTROYED
  4552                              <1> ;-------------------------------------------------------------------------------
  4553                              <1> TURN_ON:
  4554 000022B8 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4555 000022BA 88D9                <1> 	MOV	CL,BL			; CL = DRIVE #
  4556 000022BC C0C304              <1> 	ROL	BL,4			; BL = DRIVE SELECT
  4557 000022BF FA                  <1> 	CLI				; NO INTERRUPTS WHILE DETERMINING STATUS
  4558 000022C0 C605[5B6B0000]FF    <1> 	MOV	byte [MOTOR_COUNT],0FFH	; ENSURE MOTOR STAYS ON FOR OPERATION
  4559 000022C7 A0[5A6B0000]        <1> 	MOV	AL, [MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4560 000022CC 2430                <1> 	AND	AL,00110000B		; KEEP ONLY DRIVE SELECT BITS
  4561 000022CE B401                <1> 	MOV	AH,1			; MASK FOR DETERMINING MOTOR BIT
  4562 000022D0 D2E4                <1> 	SHL	AH,CL			; AH = MOTOR ON, A=00000001, B=00000010
  4563                              <1> 
  4564                              <1> ;  AL = DRIVE SELECT FROM @MOTOR_STATUS
  4565                              <1> ;  BL = DRIVE SELECT DESIRED
  4566                              <1> ;  AH = MOTOR ON MASK DESIRED
  4567                              <1> 
  4568 000022D2 38D8                <1> 	CMP	AL,BL			; REQUESTED DRIVE ALREADY SELECTED ?
  4569 000022D4 7508                <1> 	JNZ	short TURN_IT_ON	; IF NOT SELECTED JUMP
  4570 000022D6 8425[5A6B0000]      <1> 	TEST	AH, [MOTOR_STATUS]	; TEST MOTOR ON BIT
  4571 000022DC 7535                <1> 	JNZ	short NO_MOT_WAIT	; JUMP IF MOTOR ON AND SELECTED
  4572                              <1> 
  4573                              <1> TURN_IT_ON:
  4574 000022DE 08DC                <1> 	OR	AH,BL			; AH = DRIVE SELECT AND MOTOR ON
  4575 000022E0 8A3D[5A6B0000]      <1> 	MOV	BH,[MOTOR_STATUS]	; SAVE COPY OF @MOTOR_STATUS BEFORE
  4576 000022E6 80E70F              <1> 	AND	BH,00001111B		; KEEP ONLY MOTOR BITS
  4577 000022E9 8025[5A6B0000]CF    <1> 	AND	byte [MOTOR_STATUS],11001111B ; CLEAR OUT DRIVE SELECT
  4578 000022F0 0825[5A6B0000]      <1> 	OR	[MOTOR_STATUS],AH	; OR IN DRIVE SELECTED AND MOTOR ON
  4579 000022F6 A0[5A6B0000]        <1> 	MOV	AL,[MOTOR_STATUS]	; GET DIGITAL OUTPUT REGISTER REFLECTION
  4580 000022FB 88C3                <1> 	MOV	BL,AL			; BL=@MOTOR_STATUS AFTER, BH=BEFORE
  4581 000022FD 80E30F              <1> 	AND	BL,00001111B		; KEEP ONLY MOTOR BITS
  4582 00002300 FB                  <1> 	STI				; ENABLE INTERRUPTS AGAIN
  4583 00002301 243F                <1> 	AND	AL,00111111B		; STRIP AWAY UNWANTED BITS
  4584 00002303 C0C004              <1> 	ROL	AL,4			; PUT BITS IN DESIRED POSITIONS
  4585 00002306 0C0C                <1> 	OR	AL,00001100B		; NO RESET, ENABLE DMA/INTERRUPT
  4586 00002308 66BAF203            <1> 	MOV	DX,03F2H		; SELECT DRIVE AND TURN ON MOTOR
  4587 0000230C EE                  <1> 	OUT	DX,AL
  4588 0000230D 38FB                <1> 	CMP	BL,BH			; NEW MOTOR TURNED ON ?
  4589                              <1> 	;JZ	short NO_MOT_WAIT	; NO WAIT REQUIRED IF JUST SELECT
  4590 0000230F 7403                <1> 	je	short no_mot_w1 ; 27/02/2015 
  4591 00002311 F8                  <1> 	CLC				; (re)SET CARRY MEANING WAIT
  4592 00002312 C3                  <1> 	RETn
  4593                              <1> 
  4594                              <1> NO_MOT_WAIT:
  4595 00002313 FB                  <1> 	sti
  4596                              <1> no_mot_w1: ; 27/02/2015
  4597 00002314 F9                  <1> 	STC				; SET NO WAIT REQUIRED
  4598                              <1> 	;STI				; INTERRUPTS BACK ON
  4599 00002315 C3                  <1> 	RETn
  4600                              <1> 
  4601                              <1> ;-------------------------------------------------------------------------------
  4602                              <1> ; HD_WAIT
  4603                              <1> ;	WAIT FOR HEAD SETTLE TIME.
  4604                              <1> ;
  4605                              <1> ; ON ENTRY:	DI = DRIVE #
  4606                              <1> ;
  4607                              <1> ; ON EXIT:	AX,BX,CX,DX DESTROYED
  4608                              <1> ;-------------------------------------------------------------------------------
  4609                              <1> HD_WAIT:
  4610 00002316 B209                <1> 	MOV	DL,9			; GET HEAD SETTLE PARAMETER
  4611 00002318 E826FFFFFF          <1> 	CALL	GET_PARM
  4612 0000231D 08E4                <1> 	or	ah, ah	; 17/12/2014
  4613 0000231F 7519                <1> 	jnz	short DO_WAT
  4614 00002321 F605[5A6B0000]80    <1>         TEST    byte [MOTOR_STATUS],10000000B ; SEE IF A WRITE OPERATION
  4615                              <1> 	;JZ	short ISNT_WRITE	; IF NOT, DO NOT ENFORCE ANY VALUES
  4616                              <1> 	;OR	AH,AH			; CHECK FOR ANY WAIT?
  4617                              <1> 	;JNZ	short DO_WAT		; IF THERE DO NOT ENFORCE
  4618 00002328 741E                <1> 	jz	short HW_DONE
  4619 0000232A B40F                <1> 	MOV	AH,HD12_SETTLE		; LOAD 1.2M HEAD SETTLE MINIMUM
  4620 0000232C 8A87[696B0000]      <1> 	MOV	AL,[DSK_STATE+eDI]	; LOAD STATE
  4621 00002332 24C0                <1> 	AND	AL,RATE_MSK		; KEEP ONLY RATE
  4622 00002334 3C80                <1> 	CMP	AL,RATE_250		; 1.2 M DRIVE ?
  4623 00002336 7502                <1> 	JNZ	short DO_WAT		; DEFAULT HEAD SETTLE LOADED
  4624                              <1> ;GP3:
  4625 00002338 B414                <1> 	MOV	AH,HD320_SETTLE		; USE 320/360 HEAD SETTLE
  4626                              <1> ;	JMP	SHORT DO_WAT
  4627                              <1> 
  4628                              <1> ;ISNT_WRITE:
  4629                              <1> ;	OR	AH,AH			; CHECK FOR NO WAIT
  4630                              <1> ;	JZ	short HW_DONE		; IF NOT WRITE AND 0 ITS OK
  4631                              <1> 
  4632                              <1> ;-----	AH CONTAINS NUMBER OF MILLISECONDS TO WAIT
  4633                              <1> DO_WAT:
  4634                              <1> ;	MOV	AL,AH			; AL = # MILLISECONDS
  4635                              <1> ;	;XOR	AH,AH			; AX = # MILLISECONDS
  4636                              <1> J29:					; 	1 MILLISECOND LOOP
  4637                              <1> 	;mov	cx, WAIT_FDU_HEAD_SETTLE ; 33 ; 1 ms in 30 micro units.
  4638 0000233A B942000000          <1> 	MOV	eCX,66			; COUNT AT 15.085737 US PER COUNT
  4639 0000233F E879F1FFFF          <1> 	CALL	WAITF			; DELAY FOR 1 MILLISECOND
  4640                              <1> 	;DEC	AL			; DECREMENT THE COUNT
  4641 00002344 FECC                <1> 	dec	ah
  4642 00002346 75F2                <1> 	JNZ	short J29		; DO AL MILLISECOND # OF TIMES
  4643                              <1> HW_DONE:
  4644 00002348 C3                  <1> 	RETn
  4645                              <1> 
  4646                              <1> ;-------------------------------------------------------------------------------
  4647                              <1> ; NEC_OUTPUT
  4648                              <1> ;	THIS ROUTINE SENDS A BYTE TO THE NEC CONTROLLER AFTER TESTING
  4649                              <1> ;	FOR CORRECT DIRECTION AND CONTROLLER READY THIS ROUTINE WILL
  4650                              <1> ;	TIME OUT IF THE BYTE IS NOT ACCEPTED WITHIN A REASONABLE AMOUNT
  4651                              <1> ;	OF TIME, SETTING THE DISKETTE STATUS ON COMPLETION.
  4652                              <1> ; 
  4653                              <1> ; ON ENTRY: 	AH = BYTE TO BE OUTPUT
  4654                              <1> ;
  4655                              <1> ; ON EXIT:	CY = 0  SUCCESS
  4656                              <1> ;		CY = 1  FAILURE -- DISKETTE STATUS UPDATED
  4657                              <1> ;		        IF A FAILURE HAS OCCURRED, THE RETURN IS MADE ONE LEVEL
  4658                              <1> ;		        HIGHER THAN THE CALLER OF NEC OUTPUT. THIS REMOVES THE
  4659                              <1> ;		        REQUIREMENT OF TESTING AFTER EVERY CALL OF NEC_OUTPUT.
  4660                              <1> ;		AX,CX,DX DESTROYED
  4661                              <1> ;-------------------------------------------------------------------------------
  4662                              <1> 
  4663                              <1> ; 09/12/2014 [Erdogan Tan] 
  4664                              <1> ;	(from 'PS2 Hardware Interface Tech. Ref. May 88', Page 09-05.)
  4665                              <1> ; Diskette Drive Controller Status Register (3F4h)
  4666                              <1> ;	This read only register facilitates the transfer of data between
  4667                              <1> ;	the system microprocessor and the controller.
  4668                              <1> ; Bit 7 - When set to 1, the Data register is ready to transfer data 
  4669                              <1> ;	  with the system micrprocessor.
  4670                              <1> ; Bit 6 - The direction of data transfer. If this bit is set to 0,
  4671                              <1> ;	  the transfer is to the controller.
  4672                              <1> ; Bit 5 - When this bit is set to 1, the controller is in the non-DMA mode.
  4673                              <1> ; Bit 4 - When this bit is set to 1, a Read or Write command is being executed.
  4674                              <1> ; Bit 3 - Reserved.
  4675                              <1> ; Bit 2 - Reserved.
  4676                              <1> ; Bit 1 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4677                              <1> ; Bit 0 - When this bit is set to 1, dskette drive 1 is in the seek mode.
  4678                              <1> 
  4679                              <1> ; Data Register (3F5h)
  4680                              <1> ; This read/write register passes data, commands and parameters, and provides
  4681                              <1> ; diskette status information.
  4682                              <1>   		
  4683                              <1> NEC_OUTPUT:
  4684                              <1> 	;PUSH	BX			; SAVE REG.
  4685 00002349 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4686                              <1> 	;MOV	BL,2			; HIGH ORDER COUNTER
  4687                              <1> 	;XOR	CX,CX			; COUNT FOR TIME OUT
  4688                              <1> 	; 16/12/2014
  4689                              <1> 	; waiting for (max.) 0.5 seconds
  4690                              <1>         ;;mov	byte [wait_count], 0 ;; 27/02/2015
  4691                              <1> 	;
  4692                              <1> 	; 17/12/2014
  4693                              <1> 	; Modified from AWARD BIOS 1999 - ADISK.ASM - SEND_COMMAND
  4694                              <1> 	;
  4695                              <1> 	;WAIT_FOR_PORT:	Waits for a bit at a port pointed to by DX to
  4696                              <1> 	;		go on.
  4697                              <1> 	;INPUT:
  4698                              <1> 	;	AH=Mask for isolation bits.
  4699                              <1> 	;	AL=pattern to look for.
  4700                              <1> 	;	DX=Port to test for
  4701                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4702                              <1> 	;	     (normally 30 microseconds per period.)
  4703                              <1> 	;
  4704                              <1> 	;WFP_SHORT:  
  4705                              <1> 	;	Wait for port if refresh cycle is short (15-80 Us range).
  4706                              <1> 	;
  4707                              <1> 
  4708                              <1> ;	mov	bl, WAIT_FDU_SEND_HI+1	; 0+1
  4709                              <1> ;	mov	cx, WAIT_FDU_SEND_LO	; 16667
  4710 0000234D B91B410000          <1> 	mov	ecx, WAIT_FDU_SEND_LH   ; 16667 (27/02/2015)
  4711                              <1> ;
  4712                              <1> ;WFPS_OUTER_LP:
  4713                              <1> ;	;
  4714                              <1> ;WFPS_CHECK_PORT:
  4715                              <1> J23:
  4716 00002352 EC                  <1> 	IN	AL,DX			; GET STATUS
  4717 00002353 24C0                <1> 	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4718 00002355 3C80                <1> 	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4719 00002357 7418                <1> 	JZ	short J27		; STATUS AND DIRECTION OK
  4720                              <1> WFPS_HI:
  4721 00002359 E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  4722 0000235B A810                <1> 	TEST	AL,010H			; transition on memory
  4723 0000235D 75FA                <1> 	JNZ	SHORT WFPS_HI		; refresh.
  4724                              <1> WFPS_LO:
  4725 0000235F E461                <1> 	IN	AL, PORT_B		; SYS1
  4726 00002361 A810                <1> 	TEST	AL,010H
  4727 00002363 74FA                <1> 	JZ	SHORT WFPS_LO
  4728                              <1> 	;LOOP	SHORT WFPS_CHECK_PORT
  4729 00002365 E2EB                <1> 	loop	J23	; 27/02/2015
  4730                              <1> ;	;
  4731                              <1> ;	dec	bl
  4732                              <1> ;	jnz	short WFPS_OUTER_LP
  4733                              <1> ;	jmp	short WFPS_TIMEOUT	; fail
  4734                              <1> ;J23:
  4735                              <1> ;	IN	AL,DX			; GET STATUS
  4736                              <1> ;	AND	AL,11000000B		; KEEP STATUS AND DIRECTION
  4737                              <1> ;	CMP	AL,10000000B		; STATUS 1 AND DIRECTION 0 ?
  4738                              <1> ;	JZ	short J27		; STATUS AND DIRECTION OK
  4739                              <1> 	;LOOP	J23			; CONTINUE TILL CX EXHAUSTED
  4740                              <1> 	;DEC	BL			; DECREMENT COUNTER
  4741                              <1> 	;JNZ	short J23		; REPEAT TILL DELAY FINISHED, CX = 0
  4742                              <1>    
  4743                              <1> 	;;27/02/2015
  4744                              <1> 	;16/12/2014
  4745                              <1>         ;;cmp	byte [wait_count], 10   ; (10/18.2 seconds)
  4746                              <1> 	;;jb	short J23
  4747                              <1> 
  4748                              <1> ;WFPS_TIMEOUT:
  4749                              <1> 
  4750                              <1> ;-----	FALL THRU TO ERROR RETURN
  4751                              <1> 
  4752 00002367 800D[5C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  4753                              <1> 	;POP	BX			; RESTORE REG.
  4754 0000236E 58                  <1> 	POP	eAX ; 08/02/2015	; DISCARD THE RETURN ADDRESS
  4755 0000236F F9                  <1> 	STC				; INDICATE ERROR TO CALLER
  4756 00002370 C3                  <1> 	RETn
  4757                              <1> 
  4758                              <1> ;-----	DIRECTION AND STATUS OK; OUTPUT BYTE
  4759                              <1> 
  4760                              <1> J27:	
  4761 00002371 88E0                <1> 	MOV	AL,AH			; GET BYTE TO OUTPUT
  4762 00002373 6642                <1> 	INC	DX			; DATA PORT = STATUS PORT + 1
  4763 00002375 EE                  <1> 	OUT	DX,AL			; OUTPUT THE BYTE
  4764                              <1> 	;;NEWIODELAY  ;; 27/02/2015
  4765                              <1> 	; 27/02/2015
  4766 00002376 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE FLAGS
  4767                              <1> 	;MOV	eCX, 3			; 30 TO 45 MICROSECONDS WAIT FOR
  4768 00002377 29C9                <1> 	sub	ecx, ecx
  4769 00002379 B103                <1> 	mov	cl, 3 ; 24/12/2021
  4770 0000237B E83DF1FFFF          <1> 	CALL 	WAITF			; NEC FLAGS UPDATE CYCLE
  4771 00002380 9D                  <1> 	POPFd	; 24/12/2021			; RESTORE FLAGS FOR EXIT
  4772                              <1> 	;POP	BX			; RESTORE REG
  4773 00002381 C3                  <1> 	RETn				; CY = 0 FROM TEST INSTRUCTION
  4774                              <1> 
  4775                              <1> ;-------------------------------------------------------------------------------
  4776                              <1> ; SEEK
  4777                              <1> ;	THIS ROUTINE WILL MOVE THE HEAD ON THE NAMED DRIVE TO THE NAMED
  4778                              <1> ;	TRACK. IF THE DRIVE HAS NOT BEEN ACCESSED SINCE THE DRIVE
  4779                              <1> ;	RESET COMMAND WAS ISSUED, THE DRIVE WILL BE RECALIBRATED.
  4780                              <1> ;
  4781                              <1> ; ON ENTRY:	DI = DRIVE #
  4782                              <1> ;		CH = TRACK #
  4783                              <1> ;
  4784                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4785                              <1> ;		AX,BX,CX DX DESTROYED
  4786                              <1> ;-------------------------------------------------------------------------------
  4787                              <1> SEEK:
  4788 00002382 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4789 00002384 B001                <1> 	MOV	AL,1			; ESTABLISH MASK FOR RECALIBRATE TEST
  4790 00002386 86CB                <1> 	XCHG	CL,BL			; SET DRIVE VALULE INTO CL
  4791 00002388 D2C0                <1> 	ROL	AL,CL			; SHIFT MASK BY THE DRIVE VALUE
  4792 0000238A 86CB                <1> 	XCHG	CL,BL			; RECOVER TRACK VALUE
  4793 0000238C 8405[596B0000]      <1> 	TEST	AL,[SEEK_STATUS]	; TEST FOR RECALIBRATE REQUIRED
  4794 00002392 7526                <1> 	JNZ	short J28A		; JUMP IF RECALIBRATE NOT REQUIRED
  4795                              <1> 
  4796 00002394 0805[596B0000]      <1> 	OR	[SEEK_STATUS],AL	; TURN ON THE NO RECALIBRATE BIT IN FLAG
  4797 0000239A E862000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4798 0000239F 730E                <1> 	JNC	short AFT_RECAL		; RECALIBRATE DONE
  4799                              <1> 
  4800                              <1> ;-----	ISSUE RECALIBRATE FOR 80 TRACK DISKETTES
  4801                              <1> 
  4802 000023A1 C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; CLEAR OUT INVALID STATUS
  4803 000023A8 E854000000          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  4804 000023AD 7251                <1> 	JC	short RB		; IF RECALIBRATE FAILS TWICE THEN ERROR
  4805                              <1> 
  4806                              <1> AFT_RECAL:
  4807 000023AF C687[6D6B0000]00    <1>         MOV     byte [DSK_TRK+eDI],0    ; SAVE NEW CYLINDER AS PRESENT POSITION
  4808 000023B6 08ED                <1> 	OR	CH,CH			; CHECK FOR SEEK TO TRACK 0
  4809 000023B8 743F                <1> 	JZ	short DO_WAIT		; HEAD SETTLE, CY = 0 IF JUMP
  4810                              <1> 
  4811                              <1> ;-----	DRIVE IS IN SYNCHRONIZATION WITH CONTROLLER, SEEK TO TRACK
  4812                              <1> 
  4813 000023BA F687[696B0000]20    <1> J28A:	TEST	byte [DSK_STATE+eDI],DBL_STEP ; CHECK FOR DOUBLE STEP REQUIRED
  4814 000023C1 7402                <1> 	JZ	short _R7		; SINGLE STEP REQUIRED BYPASS DOUBLE
  4815 000023C3 D0E5                <1> 	SHL	CH,1			; DOUBLE NUMBER OF STEP TO TAKE
  4816                              <1> 
  4817 000023C5 3AAF[6D6B0000]      <1> _R7:	CMP	CH, [DSK_TRK+eDI]	; SEE IF ALREADY AT THE DESIRED TRACK
  4818 000023CB 7433                <1> 	JE	short RB		; IF YES, DO NOT NEED TO SEEK
  4819                              <1> 
  4820 000023CD BA[00240000]        <1> 	MOV	eDX, NEC_ERR		; LOAD RETURN ADDRESS
  4821 000023D2 52                  <1> 	PUSH	eDX ; (*)		; ON STACK FOR NEC OUTPUT ERROR
  4822 000023D3 88AF[6D6B0000]      <1> 	MOV	[DSK_TRK+eDI],CH	; SAVE NEW CYLINDER AS PRESENT POSITION
  4823 000023D9 B40F                <1> 	MOV	AH,0FH			; SEEK COMMAND TO NEC
  4824 000023DB E869FFFFFF          <1> 	CALL	NEC_OUTPUT
  4825 000023E0 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4826 000023E2 88DC                <1> 	MOV	AH,BL			; OUTPUT DRIVE NUMBER
  4827 000023E4 E860FFFFFF          <1> 	CALL	NEC_OUTPUT
  4828 000023E9 8AA7[6D6B0000]      <1> 	MOV	AH, [DSK_TRK+eDI]	; GET CYLINDER NUMBER
  4829 000023EF E855FFFFFF          <1> 	CALL	NEC_OUTPUT
  4830 000023F4 E827000000          <1> 	CALL	CHK_STAT_2		; ENDING INTERRUPT AND SENSE STATUS
  4831                              <1> 
  4832                              <1> ;-----	WAIT FOR HEAD SETTLE
  4833                              <1> 
  4834                              <1> DO_WAIT:
  4835 000023F9 9C                  <1> 	PUSHFd	; 24/12/2021		; SAVE STATUS
  4836 000023FA E817FFFFFF          <1> 	CALL	HD_WAIT			; WAIT FOR HEAD SETTLE TIME
  4837 000023FF 9D                  <1> 	POPFd	; 24/12/2021		; RESTORE STATUS
  4838                              <1> RB:
  4839                              <1> NEC_ERR:
  4840                              <1> 	; 08/02/2015 (code trick here from original IBM PC/AT DISKETTE.ASM)
  4841                              <1> 	; (*) nec_err -> retn (push edx -> pop edx) -> nec_err -> retn
  4842 00002400 C3                  <1> 	RETn				; RETURN TO CALLER
  4843                              <1> 
  4844                              <1> ;-------------------------------------------------------------------------------
  4845                              <1> ; RECAL
  4846                              <1> ;	RECALIBRATE DRIVE
  4847                              <1> ;
  4848                              <1> ; ON ENTRY:	DI = DRIVE #
  4849                              <1> ;
  4850                              <1> ; ON EXIT:	CY REFLECTS STATUS OF OPERATION.
  4851                              <1> ;-------------------------------------------------------------------------------
  4852                              <1> RECAL:
  4853                              <1> 	;PUSH	CX
  4854                              <1> 	; 24/12/2021
  4855 00002401 51                  <1> 	push	ecx
  4856 00002402 B8[1E240000]        <1> 	MOV	eAX, RC_BACK		; LOAD NEC_OUTPUT ERROR
  4857 00002407 50                  <1> 	PUSH	eAX
  4858 00002408 B407                <1> 	MOV	AH,07H			; RECALIBRATE COMMAND
  4859 0000240A E83AFFFFFF          <1> 	CALL	NEC_OUTPUT
  4860 0000240F 89FB                <1> 	MOV	eBX,eDI			; BX = DRIVE #
  4861 00002411 88DC                <1> 	MOV	AH,BL
  4862 00002413 E831FFFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT THE DRIVE NUMBER
  4863 00002418 E803000000          <1> 	CALL	CHK_STAT_2		; GET THE INTERRUPT AND SENSE INT STATUS
  4864 0000241D 58                  <1> 	POP	eAX			; THROW AWAY ERROR
  4865                              <1> RC_BACK:
  4866                              <1> 	;POP	CX
  4867                              <1> 	; 24/12/2021
  4868 0000241E 59                  <1> 	pop	ecx
  4869 0000241F C3                  <1> 	RETn
  4870                              <1> 
  4871                              <1> ;-------------------------------------------------------------------------------
  4872                              <1> ; CHK_STAT_2
  4873                              <1> ;	THIS ROUTINE HANDLES THE INTERRUPT RECEIVED AFTER RECALIBRATE,
  4874                              <1> ;	OR SEEK TO THE ADAPTER. THE INTERRUPT IS WAITED FOR, THE
  4875                              <1> ;	INTERRUPT STATUS SENSED, AND THE RESULT RETURNED TO THE CALLER.
  4876                              <1> ;
  4877                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4878                              <1> ;-------------------------------------------------------------------------------
  4879                              <1> CHK_STAT_2:
  4880 00002420 B8[48240000]        <1>         MOV     eAX, CS_BACK            ; LOAD NEC_OUTPUT ERROR ADDRESS
  4881 00002425 50                  <1> 	PUSH	eAX
  4882 00002426 E828000000          <1> 	CALL	WAIT_INT		; WAIT FOR THE INTERRUPT
  4883 0000242B 721A                <1> 	JC	short J34		; IF ERROR, RETURN IT
  4884 0000242D B408                <1> 	MOV	AH,08H			; SENSE INTERRUPT STATUS COMMAND
  4885 0000242F E815FFFFFF          <1> 	CALL	NEC_OUTPUT
  4886 00002434 E84A000000          <1> 	CALL	RESULTS			; READ IN THE RESULTS
  4887 00002439 720C                <1> 	JC	short J34
  4888 0000243B A0[5D6B0000]        <1> 	MOV	AL,[NEC_STATUS]		; GET THE FIRST STATUS BYTE
  4889 00002440 2460                <1> 	AND	AL,01100000B		; ISOLATE THE BITS
  4890 00002442 3C60                <1> 	CMP	AL,01100000B		; TEST FOR CORRECT VALUE
  4891 00002444 7403                <1> 	JZ	short J35		; IF ERROR, GO MARK IT
  4892 00002446 F8                  <1> 	CLC				; GOOD RETURN
  4893                              <1> J34:
  4894 00002447 58                  <1> 	POP	eAX			; THROW AWAY ERROR RETURN
  4895                              <1> CS_BACK:
  4896 00002448 C3                  <1> 	RETn
  4897                              <1> J35:
  4898 00002449 800D[5C6B0000]40    <1> 	OR	byte [DSKETTE_STATUS], BAD_SEEK
  4899 00002450 F9                  <1> 	STC				; ERROR RETURN CODE
  4900 00002451 EBF4                <1> 	JMP	SHORT J34
  4901                              <1> 
  4902                              <1> ;-------------------------------------------------------------------------------
  4903                              <1> ; WAIT_INT
  4904                              <1> ;	THIS ROUTINE WAITS FOR AN INTERRUPT TO OCCUR A TIME OUT ROUTINE
  4905                              <1> ;	TAKES PLACE DURING THE WAIT, SO THAT AN ERROR MAY BE RETURNED
  4906                              <1> ;	IF THE DRIVE IS NOT READY.
  4907                              <1> ;
  4908                              <1> ; ON EXIT: 	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4909                              <1> ;-------------------------------------------------------------------------------
  4910                              <1> 
  4911                              <1> ; 17/12/2014
  4912                              <1> ; 2.5 seconds waiting !
  4913                              <1> ;(AWARD BIOS - 1999, WAIT_FDU_INT_LOW, WAIT_FDU_INT_HI)
  4914                              <1> ; amount of time to wait for completion interrupt from NEC.
  4915                              <1> 
  4916                              <1> 
  4917                              <1> WAIT_INT:
  4918 00002453 FB                  <1> 	STI				; TURN ON INTERRUPTS, JUST IN CASE
  4919 00002454 F8                  <1> 	CLC				; CLEAR TIMEOUT INDICATOR
  4920                              <1>        ;MOV	BL,10			; CLEAR THE COUNTERS
  4921                              <1>        ;XOR	CX,CX			; FOR 2 SECOND WAIT
  4922                              <1> 
  4923                              <1> 	; Modification from AWARD BIOS - 1999 (ATORGS.ASM, WAIT
  4924                              <1> 	;
  4925                              <1> 	;WAIT_FOR_MEM:	
  4926                              <1> 	;	Waits for a bit at a specified memory location pointed
  4927                              <1> 	;	to by ES:[DI] to become set.
  4928                              <1> 	;INPUT:
  4929                              <1> 	;	AH=Mask to test with.
  4930                              <1> 	;	ES:[DI] = memory location to watch.
  4931                              <1> 	;	BH:CX=Number of memory refresh periods to delay.
  4932                              <1> 	;	     (normally 30 microseconds per period.)
  4933                              <1> 
  4934                              <1> 	; waiting for (max.) 2.5 secs in 30 micro units.
  4935                              <1> ;	mov 	cx, WAIT_FDU_INT_LO		; 017798
  4936                              <1> ;;	mov 	bl, WAIT_FDU_INT_HI
  4937                              <1> ;	mov 	bl, WAIT_FDU_INT_HI + 1
  4938                              <1> 	; 27/02/2015
  4939 00002455 B986450100          <1> 	mov 	ecx, WAIT_FDU_INT_LH	; 83334 (2.5 seconds)		
  4940                              <1> WFMS_CHECK_MEM:
  4941 0000245A F605[596B0000]80    <1> 	test	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4942 00002461 7516                <1>         jnz     short J37
  4943                              <1> WFMS_HI:
  4944 00002463 E461                <1> 	IN	AL,PORT_B  ; 061h	; SYS1, wait for lo to hi
  4945 00002465 A810                <1> 	TEST	AL,010H			; transition on memory
  4946 00002467 75FA                <1> 	JNZ	SHORT WFMS_HI		; refresh.
  4947                              <1> WFMS_LO:
  4948 00002469 E461                <1> 	IN	AL,PORT_B		;SYS1
  4949 0000246B A810                <1> 	TEST	AL,010H
  4950 0000246D 74FA                <1> 	JZ	SHORT WFMS_LO
  4951 0000246F E2E9                <1>         LOOP    WFMS_CHECK_MEM
  4952                              <1> ;WFMS_OUTER_LP:
  4953                              <1> ;;	or	bl, bl			; check outer counter
  4954                              <1> ;;	jz	short J36A		; WFMS_TIMEOUT
  4955                              <1> ;	dec	bl
  4956                              <1> ;	jz	short J36A	
  4957                              <1> ;	jmp	short WFMS_CHECK_MEM
  4958                              <1> 
  4959                              <1> 	;17/12/2014
  4960                              <1> 	;16/12/2014
  4961                              <1> ;	mov     byte [wait_count], 0    ; Reset (INT 08H) counter
  4962                              <1> ;J36:
  4963                              <1> ;	TEST	byte [SEEK_STATUS],INT_FLAG ; TEST FOR INTERRUPT OCCURRING
  4964                              <1> ;	JNZ	short J37
  4965                              <1> 	;16/12/2014
  4966                              <1> 	;LOOP	J36			; COUNT DOWN WHILE WAITING
  4967                              <1> 	;DEC	BL			; SECOND LEVEL COUNTER
  4968                              <1> 	;JNZ	short J36
  4969                              <1> ;       cmp     byte [wait_count], 46   ; (46/18.2 seconds)
  4970                              <1> ;	jb	short J36
  4971                              <1> 
  4972                              <1> ;WFMS_TIMEOUT:
  4973                              <1> ;J36A:
  4974 00002471 800D[5C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS], TIME_OUT ; NOTHING HAPPENED
  4975 00002478 F9                  <1> 	STC				; ERROR RETURN
  4976                              <1> J37:
  4977 00002479 9C                  <1> 	PUSHF				; SAVE CURRENT CARRY
  4978 0000247A 8025[596B0000]7F    <1> 	AND	byte [SEEK_STATUS], ~INT_FLAG ; TURN OFF INTERRUPT FLAG
  4979 00002481 9D                  <1> 	POPF				; RECOVER CARRY
  4980 00002482 C3                  <1> 	RETn				; GOOD RETURN CODE
  4981                              <1> 
  4982                              <1> ;-------------------------------------------------------------------------------
  4983                              <1> ; RESULTS
  4984                              <1> ;	THIS ROUTINE WILL READ ANYTHING THAT THE NEC CONTROLLER RETURNS 
  4985                              <1> ;	FOLLOWING AN INTERRUPT.
  4986                              <1> ;
  4987                              <1> ; ON EXIT:	@DSKETTE_STATUS, CY REFLECT STATUS OF OPERATION.
  4988                              <1> ;		AX,BX,CX,DX DESTROYED
  4989                              <1> ;-------------------------------------------------------------------------------
  4990                              <1> RESULTS:
  4991 00002483 57                  <1> 	PUSH	eDI
  4992 00002484 BF[5D6B0000]        <1> 	MOV	eDI, NEC_STATUS		; POINTER TO DATA AREA
  4993 00002489 B307                <1> 	MOV	BL,7			; MAX STATUS BYTES
  4994 0000248B 66BAF403            <1> 	MOV	DX,03F4H		; STATUS PORT
  4995                              <1> 
  4996                              <1> ;-----	WAIT FOR REQUEST FOR MASTER
  4997                              <1> 
  4998                              <1> _R10: 
  4999                              <1> 	; 16/12/2014
  5000                              <1> 	; wait for (max) 0.5 seconds
  5001                              <1> 	;MOV	BH,2			; HIGH ORDER COUNTER
  5002                              <1> 	;XOR	CX,CX			; COUNTER
  5003                              <1> 
  5004                              <1> 	;Time to wait while waiting for each byte of NEC results = .5
  5005                              <1> 	;seconds.  .5 seconds = 500,000 micros.  500,000/30 = 16,667.
  5006                              <1> 	; 27/02/2015
  5007 0000248F B91B410000          <1> 	mov 	ecx, WAIT_FDU_RESULTS_LH ; 16667  
  5008                              <1> 	;mov	cx, WAIT_FDU_RESULTS_LO  ; 16667
  5009                              <1> 	;mov	bh, WAIT_FDU_RESULTS_HI+1 ; 0+1
  5010                              <1> 
  5011                              <1> WFPSR_OUTER_LP:
  5012                              <1> 	;
  5013                              <1> WFPSR_CHECK_PORT:
  5014                              <1> J39:					; WAIT FOR MASTER
  5015 00002494 EC                  <1> 	IN	AL,DX			; GET STATUS
  5016 00002495 24C0                <1> 	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5017 00002497 3CC0                <1> 	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5018 00002499 7418                <1> 	JZ	short J42		; STATUS AND DIRECTION OK
  5019                              <1> WFPSR_HI:
  5020 0000249B E461                <1> 	IN	AL, PORT_B	;061h	; SYS1	; wait for hi to lo
  5021 0000249D A810                <1> 	TEST	AL,010H			; transition on memory
  5022 0000249F 75FA                <1> 	JNZ	SHORT WFPSR_HI		; refresh.
  5023                              <1> WFPSR_LO:
  5024 000024A1 E461                <1> 	IN	AL, PORT_B		; SYS1
  5025 000024A3 A810                <1> 	TEST	AL,010H
  5026 000024A5 74FA                <1> 	JZ	SHORT WFPSR_LO
  5027 000024A7 E2EB                <1>         LOOP    WFPSR_CHECK_PORT
  5028                              <1> 	;; 27/02/2015
  5029                              <1> 	;;dec	bh
  5030                              <1> 	;;jnz	short WFPSR_OUTER_LP
  5031                              <1> 	;jmp	short WFPSR_TIMEOUT	; fail
  5032                              <1> 
  5033                              <1> 	;;mov	byte [wait_count], 0
  5034                              <1> ;J39:					; WAIT FOR MASTER
  5035                              <1> ;	IN	AL,DX			; GET STATUS
  5036                              <1> ;	AND	AL,11000000B		; KEEP ONLY STATUS AND DIRECTION
  5037                              <1> ;	CMP	AL,11000000B		; STATUS 1 AND DIRECTION 1 ?
  5038                              <1> ;	JZ	short J42		; STATUS AND DIRECTION OK
  5039                              <1> 	;LOOP	J39			; LOOP TILL TIMEOUT
  5040                              <1> 	;DEC	BH			; DECREMENT HIGH ORDER COUNTER
  5041                              <1> 	;JNZ	short J39		; REPEAT TILL DELAY DONE
  5042                              <1> 	;
  5043                              <1> 	;;cmp	byte [wait_count], 10  ; (10/18.2 seconds)
  5044                              <1> 	;;jb	short J39	
  5045                              <1> 
  5046                              <1> ;WFPSR_TIMEOUT:
  5047 000024A9 800D[5C6B0000]80    <1> 	OR	byte [DSKETTE_STATUS],TIME_OUT
  5048 000024B0 F9                  <1> 	STC				; SET ERROR RETURN
  5049 000024B1 EB29                <1> 	JMP	SHORT POPRES		; POP REGISTERS AND RETURN
  5050                              <1> 
  5051                              <1> ;-----	READ IN THE STATUS
  5052                              <1> 
  5053                              <1> J42:
  5054 000024B3 EB00                <1> 	JMP	$+2			; I/O DELAY
  5055 000024B5 6642                <1> 	INC	DX			; POINT AT DATA PORT
  5056 000024B7 EC                  <1> 	IN	AL,DX			; GET THE DATA
  5057                              <1> 	; 16/12/2014
  5058                              <1> 	NEWIODELAY
  2154 000024B8 E6EB                <2>  out 0EBh,al
  5059 000024BA 8807                <1>         MOV     [eDI],AL                ; STORE THE BYTE
  5060 000024BC 47                  <1> 	INC	eDI			; INCREMENT THE POINTER
  5061                              <1> 	; 16/12/2014
  5062                              <1> ;	push	cx
  5063                              <1> ;	mov	cx, 30
  5064                              <1> ;wdw2:
  5065                              <1> ;	NEWIODELAY
  5066                              <1> ;	loop	wdw2
  5067                              <1> ;	pop	cx
  5068                              <1> 
  5069 000024BD B903000000          <1> 	MOV	eCX,3			; MINIMUM 24 MICROSECONDS FOR NEC
  5070 000024C2 E8F6EFFFFF          <1> 	CALL	WAITF			; WAIT 30 TO 45 MICROSECONDS
  5071 000024C7 664A                <1> 	DEC	DX			; POINT AT STATUS PORT
  5072 000024C9 EC                  <1> 	IN	AL,DX			; GET STATUS
  5073                              <1> 	; 16/12/2014
  5074                              <1> 	NEWIODELAY
  2154 000024CA E6EB                <2>  out 0EBh,al
  5075                              <1> 	;
  5076 000024CC A810                <1> 	TEST	AL,00010000B		; TEST FOR NEC STILL BUSY
  5077 000024CE 740C                <1> 	JZ	short POPRES		; RESULTS DONE ?
  5078                              <1> 
  5079 000024D0 FECB                <1> 	DEC	BL			; DECREMENT THE STATUS COUNTER
  5080 000024D2 75BB                <1>         JNZ     short _R10              ; GO BACK FOR MORE
  5081 000024D4 800D[5C6B0000]20    <1> 	OR	byte [DSKETTE_STATUS],BAD_NEC ; TOO MANY STATUS BYTES
  5082 000024DB F9                  <1> 	STC				; SET ERROR FLAG
  5083                              <1> 
  5084                              <1> ;-----	RESULT OPERATION IS DONE
  5085                              <1> POPRES:
  5086 000024DC 5F                  <1> 	POP	eDI
  5087 000024DD C3                  <1> 	RETn				; RETURN WITH CARRY SET
  5088                              <1> 
  5089                              <1> ;-------------------------------------------------------------------------------
  5090                              <1> ; READ_DSKCHNG
  5091                              <1> ;	READS THE STATE OF THE DISK CHANGE LINE.
  5092                              <1> ;
  5093                              <1> ; ON ENTRY:	DI = DRIVE #
  5094                              <1> ;
  5095                              <1> ; ON EXIT:	DI = DRIVE #
  5096                              <1> ;		ZF = 0 : DISK CHANGE LINE INACTIVE
  5097                              <1> ;		ZF = 1 : DISK CHANGE LINE ACTIVE
  5098                              <1> ;		AX,CX,DX DESTROYED
  5099                              <1> ;-------------------------------------------------------------------------------
  5100                              <1> READ_DSKCHNG:
  5101 000024DE E8A5FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON THE MOTOR IF OFF
  5102 000024E3 66BAF703            <1> 	MOV	DX,03F7H		; ADDRESS DIGITAL INPUT REGISTER
  5103 000024E7 EC                  <1> 	IN	AL,DX			; INPUT DIGITAL INPUT REGISTER
  5104 000024E8 A880                <1> 	TEST	AL,DSK_CHG		; CHECK FOR DISK CHANGE LINE ACTIVE
  5105 000024EA C3                  <1> 	RETn				; RETURN TO CALLER WITH ZERO FLAG SET
  5106                              <1> 
  5107                              <1> ;-------------------------------------------------------------------------------
  5108                              <1> ; DRIVE_DET
  5109                              <1> ;	DETERMINES WHETHER DRIVE IS 80 OR 40 TRACKS AND
  5110                              <1> ;	UPDATES STATE INFORMATION ACCORDINGLY.
  5111                              <1> ; ON ENTRY:	DI = DRIVE #
  5112                              <1> ;-------------------------------------------------------------------------------
  5113                              <1> DRIVE_DET:
  5114 000024EB E898FDFFFF          <1> 	CALL	MOTOR_ON		; TURN ON MOTOR IF NOT ALREADY ON
  5115 000024F0 E80CFFFFFF          <1> 	CALL	RECAL			; RECALIBRATE DRIVE
  5116 000024F5 724F                <1> 	JC	short DD_BAC		; ASSUME NO DRIVE PRESENT
  5117 000024F7 B530                <1> 	MOV	CH,TRK_SLAP		; SEEK TO TRACK 48
  5118 000024F9 E884FEFFFF          <1> 	CALL	SEEK
  5119 000024FE 7246                <1> 	JC	short DD_BAC		; ERROR NO DRIVE
  5120 00002500 B50B                <1> 	MOV	CH,QUIET_SEEK+1		; SEEK TO TRACK 10
  5121                              <1> SK_GIN:
  5122 00002502 FECD                <1> 	DEC	CH			; DECREMENT TO NEXT TRACK
  5123                              <1> 	;PUSH	CX			; SAVE TRACK
  5124                              <1> 	; 24/12/2021
  5125 00002504 51                  <1> 	push	ecx
  5126 00002505 E878FEFFFF          <1> 	CALL	SEEK
  5127 0000250A 723B                <1> 	JC	short POP_BAC		; POP AND RETURN
  5128 0000250C B8[47250000]        <1> 	MOV	eAX, POP_BAC		; LOAD NEC OUTPUT ERROR ADDRESS
  5129 00002511 50                  <1> 	PUSH	eAX
  5130 00002512 B404                <1> 	MOV	AH,SENSE_DRV_ST		; SENSE DRIVE STATUS COMMAND BYTE
  5131 00002514 E830FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5132 00002519 6689F8              <1> 	MOV	AX,DI			; AL = DRIVE
  5133 0000251C 88C4                <1> 	MOV	AH,AL			; AH = DRIVE
  5134 0000251E E826FEFFFF          <1> 	CALL	NEC_OUTPUT		; OUTPUT TO NEC
  5135 00002523 E85BFFFFFF          <1> 	CALL	RESULTS			; GO GET STATUS
  5136 00002528 58                  <1> 	POP	eAX			; THROW AWAY ERROR ADDRESS
  5137                              <1> 	;POP	CX			; RESTORE TRACK
  5138                              <1> 	; 24/12/2021
  5139 00002529 59                  <1> 	pop	ecx
  5140 0000252A F605[5D6B0000]10    <1> 	TEST	byte [NEC_STATUS], HOME	; TRACK 0 ?
  5141 00002531 74CF                <1> 	JZ	short SK_GIN		; GO TILL TRACK 0
  5142 00002533 08ED                <1> 	OR	CH,CH			; IS HOME AT TRACK 0
  5143 00002535 7408                <1> 	JZ	short IS_80		; MUST BE 80 TRACK DRIVE
  5144                              <1> 
  5145                              <1> ;	DRIVE IS A 360; SET DRIVE TO DETERMINED;
  5146                              <1> ;	SET MEDIA TO DETERMINED AT RATE 250.
  5147                              <1> 
  5148 00002537 808F[696B0000]94    <1> 	OR	byte [DSK_STATE+eDI], DRV_DET+MED_DET+RATE_250
  5149 0000253E C3                  <1> 	RETn				; ALL INFORMATION SET
  5150                              <1> IS_80:
  5151 0000253F 808F[696B0000]01    <1> 	OR	byte [DSK_STATE+eDI], TRK_CAPA ; SETUP 80 TRACK CAPABILITY
  5152                              <1> DD_BAC:
  5153 00002546 C3                  <1> 	RETn
  5154                              <1> POP_BAC:
  5155                              <1> 	;POP	CX			; THROW AWAY
  5156                              <1> 	; 24/12/2021
  5157 00002547 59                  <1> 	pop	ecx
  5158 00002548 C3                  <1> 	RETn
  5159                              <1> 
  5160                              <1> fdc_int:  
  5161                              <1> 	  ; 30/07/2015	
  5162                              <1> 	  ; 16/02/2015
  5163                              <1> ;int_0Eh: ; 11/12/2014
  5164                              <1> 
  5165                              <1> ;--- HARDWARE INT 0EH -- ( IRQ LEVEL  6 ) --------------------------------------
  5166                              <1> ; DISK_INT
  5167                              <1> ;	THIS ROUTINE HANDLES THE DISKETTE INTERRUPT.
  5168                              <1> ;
  5169                              <1> ; ON EXIT:	THE INTERRUPT FLAG IS SET IN @SEEK_STATUS.
  5170                              <1> ;-------------------------------------------------------------------------------
  5171                              <1> DISK_INT_1:
  5172                              <1> 
  5173                              <1> 	;PUSH	AX			; SAVE WORK REGISTER
  5174                              <1> 	; 24/12/2021
  5175 00002549 50                  <1> 	push	eax
  5176 0000254A 1E                  <1> 	push	ds
  5177 0000254B 66B81000            <1> 	mov	ax, KDATA
  5178 0000254F 8ED8                <1> 	mov 	ds, ax
  5179 00002551 800D[596B0000]80    <1>         OR      byte [SEEK_STATUS], INT_FLAG ; TURN ON INTERRUPT OCCURRED
  5180 00002558 B020                <1> 	MOV     AL,EOI                  ; END OF INTERRUPT MARKER
  5181 0000255A E620                <1> 	OUT	INTA00,AL		; INTERRUPT CONTROL PORT
  5182 0000255C 1F                  <1> 	pop	ds
  5183                              <1> 	;POP	AX			; RECOVER REGISTER
  5184                              <1> 	; 24/12/2021
  5185 0000255D 58                  <1> 	pop	eax
  5186 0000255E CF                  <1> 	IRETd				; RETURN FROM INTERRUPT
  5187                              <1> 
  5188                              <1> ;-------------------------------------------------------------------------------
  5189                              <1> ; DSKETTE_SETUP
  5190                              <1> ;	THIS ROUTINE DOES A PRELIMINARY CHECK TO SEE WHAT TYPE OF
  5191                              <1> ;	DISKETTE DRIVES ARE ATTACH TO THE SYSTEM.
  5192                              <1> ;-------------------------------------------------------------------------------
  5193                              <1> DSKETTE_SETUP:
  5194                              <1> 	;PUSH	AX			; SAVE REGISTERS
  5195                              <1> 	;PUSH	BX
  5196                              <1> 	;PUSH	CX
  5197 0000255F 52                  <1> 	PUSH	eDX
  5198                              <1> 	;PUSH	DI
  5199                              <1> 	;;PUSH	DS
  5200                              <1> 	; 14/12/2014
  5201                              <1> 	;mov	word [DISK_POINTER], MD_TBL6
  5202                              <1> 	;mov	[DISK_POINTER+2], cs
  5203                              <1> 	;
  5204                              <1> 	;OR	byte [RTC_WAIT_FLAG], 1	; NO RTC WAIT, FORCE USE OF LOOP
  5205 00002560 31FF                <1> 	XOR	eDI,eDI			; INITIALIZE DRIVE POINTER
  5206 00002562 66C705[696B0000]00- <1> 	MOV	WORD [DSK_STATE],0	; INITIALIZE STATES
  5206 0000256A 00                  <1>
  5207 0000256B 8025[646B0000]33    <1> 	AND	byte [LASTRATE],~(STRT_MSK+SEND_MSK) ; CLEAR START & SEND
  5208 00002572 800D[646B0000]C0    <1> 	OR	byte [LASTRATE],SEND_MSK ; INITIALIZE SENT TO IMPOSSIBLE
  5209 00002579 C605[596B0000]00    <1> 	MOV	byte [SEEK_STATUS],0	; INDICATE RECALIBRATE NEEDED
  5210 00002580 C605[5B6B0000]00    <1> 	MOV	byte [MOTOR_COUNT],0	; INITIALIZE MOTOR COUNT
  5211 00002587 C605[5A6B0000]00    <1> 	MOV	byte [MOTOR_STATUS],0	; INITIALIZE DRIVES TO OFF STATE
  5212 0000258E C605[5C6B0000]00    <1> 	MOV	byte [DSKETTE_STATUS],0	; NO ERRORS
  5213                              <1> 	;
  5214                              <1> 	; 28/02/2015
  5215                              <1> 	;mov	word [cfd], 100h 
  5216 00002595 E89DF2FFFF          <1> 	call	DSK_RESET
  5217 0000259A 5A                  <1> 	pop	edx
  5218 0000259B C3                  <1> 	retn
  5219                              <1> 
  5220                              <1> ;SUP0:
  5221                              <1> ;	CALL	DRIVE_DET		; DETERMINE DRIVE
  5222                              <1> ;	CALL	XLAT_OLD		; TRANSLATE STATE TO COMPATIBLE MODE
  5223                              <1> ;	; 02/01/2015
  5224                              <1> ;	;INC	DI			; POINT TO NEXT DRIVE
  5225                              <1> ;	;CMP	DI,MAX_DRV		; SEE IF DONE
  5226                              <1> ;	;JNZ	short SUP0		; REPEAT FOR EACH ORIVE
  5227                              <1> ;       cmp     byte [fd1_type], 0	
  5228                              <1> ;	jna	short sup1
  5229                              <1> ;	or	di, di
  5230                              <1> ;	jnz	short sup1
  5231                              <1> ;	inc	di
  5232                              <1> ;       jmp     short SUP0
  5233                              <1> ;sup1:
  5234                              <1> ;	MOV	byte [SEEK_STATUS],0	; FORCE RECALIBRATE
  5235                              <1> ;	;AND	byte [RTC_WAIT_FLAG],0FEH ; ALLOW FOR RTC WAIT
  5236                              <1> ;	CALL	SETUP_END		; VARIOUS CLEANUPS
  5237                              <1> ;	;;POP	DS			; RESTORE CALLERS REGISTERS
  5238                              <1> ;	;POP	DI
  5239                              <1> ;	POP	eDX
  5240                              <1> ;	;POP	CX
  5241                              <1> ;	;POP	BX
  5242                              <1> ;	;POP	AX
  5243                              <1> ;	RETn
  5244                              <1> 
  5245                              <1> ;//////////////////////////////////////////////////////
  5246                              <1> ;; END OF DISKETTE I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  5247                              <1> ;
  5248                              <1> 
  5249                              <1> int13h: ; 21/02/2015
  5250 0000259C 9C                  <1> 	pushfd
  5251 0000259D 0E                  <1> 	push 	cs
  5252 0000259E E858000000          <1> 	call 	DISK_IO
  5253 000025A3 C3                  <1> 	retn
  5254                              <1> 
  5255                              <1> ;;;;;; DISK I/O ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 21/02/2015 ;;;
  5256                              <1> ;/////////////////////////////////////////////////////////////////////
  5257                              <1> 
  5258                              <1> ; DISK I/O - Erdogan Tan (Retro UNIX 386 v1 project)
  5259                              <1> ; 23/02/2015
  5260                              <1> ; 21/02/2015 (unix386.s)
  5261                              <1> ; 22/12/2014 - 14/02/2015 (dsectrm2.s)
  5262                              <1> ;
  5263                              <1> ; Original Source Code:
  5264                              <1> ; DISK ----- 09/25/85 FIXED DISK BIOS
  5265                              <1> ; (IBM PC XT Model 286 System BIOS Source Code, 04-21-86)
  5266                              <1> ;
  5267                              <1> ; Modifications: by reference of AWARD BIOS 1999 (D1A0622) 
  5268                              <1> ;		 Source Code - ATORGS.ASM, AHDSK.ASM
  5269                              <1> ;
  5270                              <1> 
  5271                              <1> ;The wait for controller to be not busy is 10 seconds.
  5272                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5273                              <1> ;;WAIT_HDU_CTLR_BUSY_LO	equ	1615h		
  5274                              <1> ;;WAIT_HDU_CTLR_BUSY_HI	equ	  05h
  5275                              <1> WAIT_HDU_CTRL_BUSY_LH	equ	51615h	 ;21/02/2015		
  5276                              <1> 
  5277                              <1> ;The wait for controller to issue completion interrupt is 10 seconds.
  5278                              <1> ;10,000,000 / 30 = 333,333.  333,333 decimal = 051615h
  5279                              <1> ;;WAIT_HDU_INT_LO	equ	1615h
  5280                              <1> ;;WAIT_HDU_INT_HI	equ	  05h
  5281                              <1> WAIT_HDU_INT_LH		equ	51615h	; 21/02/2015
  5282                              <1> 
  5283                              <1> ;The wait for Data request on read and write longs is
  5284                              <1> ;2000 us. (?)
  5285                              <1> ;;WAIT_HDU_DRQ_LO	equ	1000	; 03E8h
  5286                              <1> ;;WAIT_HDU_DRQ_HI	equ	0
  5287                              <1> WAIT_HDU_DRQ_LH		equ	1000	; 21/02/2015
  5288                              <1> 
  5289                              <1> ; Port 61h (PORT_B)
  5290                              <1> SYS1		equ	61h	; PORT_B  (diskette.inc)
  5291                              <1> 
  5292                              <1> ; 23/12/2014
  5293                              <1> %define CMD_BLOCK       eBP-8  ; 21/02/2015
  5294                              <1> 
  5295                              <1> ;--- INT 13H -------------------------------------------------------------------
  5296                              <1> ;									       :
  5297                              <1> ; FIXED DISK I/O INTERFACE						       :
  5298                              <1> ;									       :
  5299                              <1> ;	THIS INTERFACE PROVIDES ACCESS TO 5 1/4" FIXED DISKS THROUGH           :
  5300                              <1> ;	THE IBM FIXED DISK CONTROLLER.					       :
  5301                              <1> ;									       :
  5302                              <1> ;	THE  BIOS  ROUTINES  ARE  MEANT  TO  BE  ACCESSED  THROUGH	       :
  5303                              <1> ;	SOFTWARE  INTERRUPTS  ONLY.    ANY  ADDRESSES  PRESENT	IN	       :
  5304                              <1> ;	THESE  LISTINGS  ARE  INCLUDED	 ONLY	FOR  COMPLETENESS,	       :
  5305                              <1> ;	NOT  FOR  REFERENCE.  APPLICATIONS   WHICH  REFERENCE  ANY	       :
  5306                              <1> ;	ABSOLUTE  ADDRESSES  WITHIN  THE  CODE	SEGMENTS  OF  BIOS	       :
  5307                              <1> ;	VIOLATE  THE  STRUCTURE  AND  DESIGN  OF  BIOS. 		       :
  5308                              <1> ;									       :
  5309                              <1> ;------------------------------------------------------------------------------:
  5310                              <1> ;									       :
  5311                              <1> ; INPUT  (AH)= HEX COMMAND VALUE					       :
  5312                              <1> ;									       :
  5313                              <1> ;	(AH)= 00H  RESET DISK (DL = 80H,81H) / DISKETTE 		       :
  5314                              <1> ;	(AH)= 01H  READ THE STATUS OF THE LAST DISK OPERATION INTO (AL)        :
  5315                              <1> ;		    NOTE: DL < 80H - DISKETTE				       :
  5316                              <1> ;			  DL > 80H - DISK				       :
  5317                              <1> ;	(AH)= 02H  READ THE DESIRED SECTORS INTO MEMORY 		       :
  5318                              <1> ;	(AH)= 03H  WRITE THE DESIRED SECTORS FROM MEMORY		       :
  5319                              <1> ;	(AH)= 04H  VERIFY THE DESIRED SECTORS				       :
  5320                              <1> ;	(AH)= 05H  FORMAT THE DESIRED TRACK				       :
  5321                              <1> ;	(AH)= 06H  UNUSED						       :
  5322                              <1> ;	(AH)= 07H  UNUSED						       :
  5323                              <1> ;	(AH)= 08H  RETURN THE CURRENT DRIVE PARAMETERS			       :
  5324                              <1> ;	(AH)= 09H  INITIALIZE DRIVE PAIR CHARACTERISTICS		       :
  5325                              <1> ;		    INTERRUPT 41 POINTS TO DATA BLOCK FOR DRIVE 0	       :
  5326                              <1> ;		    INTERRUPT 46 POINTS TO DATA BLOCK FOR DRIVE 1	       :
  5327                              <1> ;	(AH)= 0AH  READ LONG						       :
  5328                              <1> ;	(AH)= 0BH  WRITE LONG  (READ & WRITE LONG ENCOMPASS 512 + 4 BYTES ECC) :
  5329                              <1> ;	(AH)= 0CH  SEEK 						       :
  5330                              <1> ;	(AH)= 0DH  ALTERNATE DISK RESET (SEE DL)			       :
  5331                              <1> ;	(AH)= 0EH  UNUSED						       :
  5332                              <1> ;	(AH)= 0FH  UNUSED						       :
  5333                              <1> ;	(AH)= 10H  TEST DRIVE READY					       :
  5334                              <1> ;	(AH)= 11H  RECALIBRATE						       :
  5335                              <1> ;	(AH)= 12H  UNUSED						       :
  5336                              <1> ;	(AH)= 13H  UNUSED						       :
  5337                              <1> ;	(AH)= 14H  CONTROLLER INTERNAL DIAGNOSTIC			       :
  5338                              <1> ;	(AH)= 15H  READ DASD TYPE					       :
  5339                              <1> ;									       :
  5340                              <1> ;-------------------------------------------------------------------------------
  5341                              <1> ;									       :
  5342                              <1> ;	REGISTERS USED FOR FIXED DISK OPERATIONS			       :
  5343                              <1> ;									       :
  5344                              <1> ;		(DL)	-  DRIVE NUMBER     (80H-81H FOR DISK. VALUE CHECKED)  :
  5345                              <1> ;		(DH)	-  HEAD NUMBER	    (0-15 ALLOWED, NOT VALUE CHECKED)  :
  5346                              <1> ;		(CH)	-  CYLINDER NUMBER  (0-1023, NOT VALUE CHECKED)(SEE CL):
  5347                              <1> ;		(CL)	-  SECTOR NUMBER    (1-17, NOT VALUE CHECKED)	       :
  5348                              <1> ;									       :
  5349                              <1> ;			   NOTE: HIGH 2 BITS OF CYLINDER NUMBER ARE PLACED     :
  5350                              <1> ;				 IN THE HIGH 2 BITS OF THE CL REGISTER	       :
  5351                              <1> ;				 (10 BITS TOTAL)			       :
  5352                              <1> ;									       :
  5353                              <1> ;		(AL)	-  NUMBER OF SECTORS (MAXIMUM POSSIBLE RANGE 1-80H,    :
  5354                              <1> ;					      FOR READ/WRITE LONG 1-79H)       :
  5355                              <1> ;									       :
  5356                              <1> ;		(ES:BX) -  ADDRESS OF BUFFER FOR READS AND WRITES,	       :
  5357                              <1> ;			   (NOT REQUIRED FOR VERIFY)			       :
  5358                              <1> ;									       :
  5359                              <1> ;		FORMAT (AH=5) ES:BX POINTS TO A 512 BYTE BUFFER. THE FIRST     :
  5360                              <1> ;			   2*(SECTORS/TRACK) BYTES CONTAIN F,N FOR EACH SECTOR.:
  5361                              <1> ;			   F = 00H FOR A GOOD SECTOR			       :
  5362                              <1> ;			       80H FOR A BAD SECTOR			       :
  5363                              <1> ;			   N = SECTOR NUMBER				       :
  5364                              <1> ;			   FOR AN INTERLEAVE OF 2 AND 17 SECTORS/TRACK	       :
  5365                              <1> ;			   THE TABLE SHOULD BE: 			       :
  5366                              <1> ;									       :
  5367                              <1> ;		   DB	   00H,01H,00H,0AH,00H,02H,00H,0BH,00H,03H,00H,0CH     :
  5368                              <1> ;		   DB	   00H,04H,00H,0DH,00H,05H,00H,0EH,00H,06H,00H,0FH     :
  5369                              <1> ;		   DB	   00H,07H,00H,10H,00H,08H,00H,11H,00H,09H	       :
  5370                              <1> ;									       :
  5371                              <1> ;-------------------------------------------------------------------------------
  5372                              <1> 
  5373                              <1> ;-------------------------------------------------------------------------------
  5374                              <1> ; OUTPUT								       :
  5375                              <1> ;	AH = STATUS OF CURRENT OPERATION				       :
  5376                              <1> ;	     STATUS BITS ARE DEFINED IN THE EQUATES BELOW		       :
  5377                              <1> ;	CY = 0	SUCCESSFUL OPERATION (AH=0 ON RETURN)			       :
  5378                              <1> ;	CY = 1	FAILED OPERATION (AH HAS ERROR REASON)			       :
  5379                              <1> ;									       :
  5380                              <1> ;	NOTE:	ERROR 11H  INDICATES THAT THE DATA READ HAD A RECOVERABLE      :
  5381                              <1> ;		ERROR WHICH WAS CORRECTED BY THE ECC ALGORITHM.  THE DATA      :
  5382                              <1> ;		IS PROBABLY GOOD,   HOWEVER THE BIOS ROUTINE INDICATES AN      :
  5383                              <1> ;		ERROR TO ALLOW THE CONTROLLING PROGRAM A CHANCE TO DECIDE      :
  5384                              <1> ;		FOR ITSELF.  THE  ERROR  MAY  NOT  RECUR  IF  THE DATA IS      :
  5385                              <1> ;		REWRITTEN.						       :
  5386                              <1> ;									       :
  5387                              <1> ;	IF DRIVE PARAMETERS WERE REQUESTED (DL >= 80H), 		       :
  5388                              <1> ;	   INPUT:							       :
  5389                              <1> ;	     (DL) = DRIVE NUMBER					       :
  5390                              <1> ;	   OUTPUT:							       :
  5391                              <1> ;	     (DL) = NUMBER OF CONSECUTIVE ACKNOWLEDGING DRIVES ATTACHED (1-2)  :
  5392                              <1> ;		    (CONTROLLER CARD ZERO TALLY ONLY)			       :
  5393                              <1> ;	     (DH) = MAXIMUM USEABLE VALUE FOR HEAD NUMBER		       :
  5394                              <1> ;	     (CH) = MAXIMUM USEABLE VALUE FOR CYLINDER NUMBER		       :
  5395                              <1> ;	     (CL) = MAXIMUM USEABLE VALUE FOR SECTOR NUMBER		       :
  5396                              <1> ;		    AND CYLINDER NUMBER HIGH BITS			       :
  5397                              <1> ;									       :
  5398                              <1> ;	IF READ DASD TYPE WAS REQUESTED,				       :
  5399                              <1> ;									       :
  5400                              <1> ;	AH = 0 - NOT PRESENT						       :
  5401                              <1> ;	     1 - DISKETTE - NO CHANGE LINE AVAILABLE			       :
  5402                              <1> ;	     2 - DISKETTE - CHANGE LINE AVAILABLE			       :
  5403                              <1> ;	     3 - FIXED DISK						       :
  5404                              <1> ;									       :
  5405                              <1> ;	CX,DX = NUMBER OF 512 BYTE BLOCKS WHEN AH = 3			       :
  5406                              <1> ;									       :
  5407                              <1> ;	REGISTERS WILL BE PRESERVED EXCEPT WHEN THEY ARE USED TO RETURN        :
  5408                              <1> ;	INFORMATION.							       :
  5409                              <1> ;									       :
  5410                              <1> ;	NOTE: IF AN ERROR IS REPORTED BY THE DISK CODE, THE APPROPRIATE        :
  5411                              <1> ;		ACTION IS TO RESET THE DISK, THEN RETRY THE OPERATION.	       :
  5412                              <1> ;									       :
  5413                              <1> ;-------------------------------------------------------------------------------
  5414                              <1> 
  5415                              <1> SENSE_FAIL	EQU	0FFH		; NOT IMPLEMENTED
  5416                              <1> NO_ERR		EQU	0E0H		; STATUS ERROR/ERROR REGISTER=0
  5417                              <1> WRITE_FAULT	EQU	0CCH		; WRITE FAULT ON SELECTED DRIVE
  5418                              <1> UNDEF_ERR	EQU	0BBH		; UNDEFINED ERROR OCCURRED
  5419                              <1> NOT_RDY 	EQU	0AAH		; DRIVE NOT READY
  5420                              <1> TIME_OUT	EQU	80H		; ATTACHMENT FAILED TO RESPOND
  5421                              <1> BAD_SEEK	EQU	40H		; SEEK OPERATION FAILED
  5422                              <1> BAD_CNTLR	EQU	20H		; CONTROLLER HAS FAILED
  5423                              <1> DATA_CORRECTED	EQU	11H		; ECC CORRECTED DATA ERROR
  5424                              <1> BAD_ECC 	EQU	10H		; BAD ECC ON DISK READ
  5425                              <1> BAD_TRACK	EQU	0BH		; NOT IMPLEMENTED
  5426                              <1> BAD_SECTOR	EQU	0AH		; BAD SECTOR FLAG DETECTED
  5427                              <1> ;DMA_BOUNDARY	EQU	09H		; DATA EXTENDS TOO FAR
  5428                              <1> INIT_FAIL	EQU	07H		; DRIVE PARAMETER ACTIVITY FAILED
  5429                              <1> BAD_RESET	EQU	05H		; RESET FAILED
  5430                              <1> ;RECORD_NOT_FND	EQU	04H		; REQUESTED SECTOR NOT FOUND
  5431                              <1> ;BAD_ADDR_MARK	EQU	02H		; ADDRESS MARK NOT FOUND
  5432                              <1> ;BAD_CMD 	EQU	01H		; BAD COMMAND PASSED TO DISK I/O
  5433                              <1> 
  5434                              <1> ;--------------------------------------------------------
  5435                              <1> ;							:
  5436                              <1> ; FIXED DISK PARAMETER TABLE				:
  5437                              <1> ;  -  THE TABLE IS COMPOSED OF A BLOCK DEFINED AS:	:
  5438                              <1> ;							:
  5439                              <1> ;  +0	(1 WORD) - MAXIMUM NUMBER OF CYLINDERS		:
  5440                              <1> ;  +2	(1 BYTE) - MAXIMUM NUMBER OF HEADS		:
  5441                              <1> ;  +3	(1 WORD) - NOT USED/SEE PC-XT			:
  5442                              <1> ;  +5	(1 WORD) - STARTING WRITE PRECOMPENSATION CYL	:
  5443                              <1> ;  +7	(1 BYTE) - MAXIMUM ECC DATA BURST LENGTH	:
  5444                              <1> ;  +8	(1 BYTE) - CONTROL BYTE 			:
  5445                              <1> ;		   BIT	  7 DISABLE RETRIES -OR-	:
  5446                              <1> ;		   BIT	  6 DISABLE RETRIES		:
  5447                              <1> ;		   BIT	  3 MORE THAN 8 HEADS		:
  5448                              <1> ;  +9	(3 BYTES)- NOT USED/SEE PC-XT			:
  5449                              <1> ; +12	(1 WORD) - LANDING ZONE 			:
  5450                              <1> ; +14	(1 BYTE) - NUMBER OF SECTORS/TRACK		:
  5451                              <1> ; +15	(1 BYTE) - RESERVED FOR FUTURE USE		:
  5452                              <1> ;							:
  5453                              <1> ;	 - TO DYNAMICALLY DEFINE A SET OF PARAMETERS	:
  5454                              <1> ;	   BUILD A TABLE FOR UP TO 15 TYPES AND PLACE	:
  5455                              <1> ;	   THE CORRESPONDING VECTOR INTO INTERRUPT 41	:
  5456                              <1> ;	   FOR DRIVE 0 AND INTERRUPT 46 FOR DRIVE 1.	:
  5457                              <1> ;							:
  5458                              <1> ;--------------------------------------------------------
  5459                              <1> 
  5460                              <1> ;--------------------------------------------------------
  5461                              <1> ;							:
  5462                              <1> ; HARDWARE SPECIFIC VALUES				:
  5463                              <1> ;							:
  5464                              <1> ;  -  CONTROLLER I/O PORT				:
  5465                              <1> ;							:
  5466                              <1> ;     > WHEN READ FROM: 				:
  5467                              <1> ;	HF_PORT+0 - READ DATA (FROM CONTROLLER TO CPU)	:
  5468                              <1> ;	HF_PORT+1 - GET ERROR REGISTER			:
  5469                              <1> ;	HF_PORT+2 - GET SECTOR COUNT			:
  5470                              <1> ;	HF_PORT+3 - GET SECTOR NUMBER			:
  5471                              <1> ;	HF_PORT+4 - GET CYLINDER LOW			:
  5472                              <1> ;	HF_PORT+5 - GET CYLINDER HIGH (2 BITS)		:
  5473                              <1> ;	HF_PORT+6 - GET SIZE/DRIVE/HEAD 		:
  5474                              <1> ;	HF_PORT+7 - GET STATUS REGISTER 		:
  5475                              <1> ;							:
  5476                              <1> ;     > WHEN WRITTEN TO:				:
  5477                              <1> ;	HF_PORT+0 - WRITE DATA (FROM CPU TO CONTROLLER) :
  5478                              <1> ;	HF_PORT+1 - SET PRECOMPENSATION CYLINDER	:
  5479                              <1> ;	HF_PORT+2 - SET SECTOR COUNT			:
  5480                              <1> ;	HF_PORT+3 - SET SECTOR NUMBER			:
  5481                              <1> ;	HF_PORT+4 - SET CYLINDER LOW			:
  5482                              <1> ;	HF_PORT+5 - SET CYLINDER HIGH (2 BITS)		:
  5483                              <1> ;	HF_PORT+6 - SET SIZE/DRIVE/HEAD 		:
  5484                              <1> ;	HF_PORT+7 - SET COMMAND REGISTER		:
  5485                              <1> ;							:
  5486                              <1> ;--------------------------------------------------------
  5487                              <1> 
  5488                              <1> ;HF_PORT 	EQU	01F0H	; DISK PORT
  5489                              <1> ;HF1_PORT	equ	0170h	
  5490                              <1> ;HF_REG_PORT	EQU	03F6H
  5491                              <1> ;HF1_REG_PORT	equ	0376h
  5492                              <1> 
  5493                              <1> HDC1_BASEPORT	equ	1F0h
  5494                              <1> HDC2_BASEPORT	equ	170h		
  5495                              <1> 
  5496                              <1> align 2
  5497                              <1> 
  5498                              <1> ;-----		STATUS REGISTER
  5499                              <1> 
  5500                              <1> ST_ERROR	EQU	00000001B	;
  5501                              <1> ST_INDEX	EQU	00000010B	;
  5502                              <1> ST_CORRCTD	EQU	00000100B	; ECC CORRECTION SUCCESSFUL
  5503                              <1> ST_DRQ		EQU	00001000B	;
  5504                              <1> ST_SEEK_COMPL	EQU	00010000B	; SEEK COMPLETE
  5505                              <1> ST_WRT_FLT	EQU	00100000B	; WRITE FAULT
  5506                              <1> ST_READY	EQU	01000000B	;
  5507                              <1> ST_BUSY 	EQU	10000000B	;
  5508                              <1> 
  5509                              <1> ;-----		ERROR REGISTER
  5510                              <1> 
  5511                              <1> ERR_DAM 	EQU	00000001B	; DATA ADDRESS MARK NOT FOUND
  5512                              <1> ERR_TRK_0	EQU	00000010B	; TRACK 0 NOT FOUND ON RECAL
  5513                              <1> ERR_ABORT	EQU	00000100B	; ABORTED COMMAND
  5514                              <1> ;		EQU	00001000B	; NOT USED
  5515                              <1> ERR_ID		EQU	00010000B	; ID NOT FOUND
  5516                              <1> ;		EQU	00100000B	; NOT USED
  5517                              <1> ERR_DATA_ECC	EQU	01000000B
  5518                              <1> ERR_BAD_BLOCK	EQU	10000000B
  5519                              <1> 
  5520                              <1> 
  5521                              <1> RECAL_CMD	EQU	00010000B	; DRIVE RECAL	(10H)
  5522                              <1> READ_CMD	EQU	00100000B	;	READ	(20H)
  5523                              <1> WRITE_CMD	EQU	00110000B	;	WRITE	(30H)
  5524                              <1> VERIFY_CMD	EQU	01000000B	;	VERIFY	(40H)
  5525                              <1> FMTTRK_CMD	EQU	01010000B	; FORMAT TRACK	(50H)
  5526                              <1> INIT_CMD	EQU	01100000B	;   INITIALIZE	(60H)
  5527                              <1> SEEK_CMD	EQU	01110000B	;	SEEK	(70H)
  5528                              <1> DIAG_CMD	EQU	10010000B	; DIAGNOSTIC	(90H)
  5529                              <1> SET_PARM_CMD	EQU	10010001B	; DRIVE PARMS	(91H)
  5530                              <1> NO_RETRIES	EQU	00000001B	; CHD MODIFIER	(01H)
  5531                              <1> ECC_MODE	EQU	00000010B	; CMD MODIFIER	(02H)
  5532                              <1> BUFFER_MODE	EQU	00001000B	; CMD MODIFIER	(08H)
  5533                              <1> 
  5534                              <1> ;MAX_FILE	EQU	2
  5535                              <1> ;S_MAX_FILE	EQU	2
  5536                              <1> MAX_FILE	equ	4		; 22/12/2014
  5537                              <1> S_MAX_FILE	equ	4		; 22/12/2014
  5538                              <1> 
  5539                              <1> DELAY_1 	EQU	25H		; DELAY FOR OPERATION COMPLETE
  5540                              <1> DELAY_2 	EQU	0600H		; DELAY FOR READY
  5541                              <1> DELAY_3 	EQU	0100H		; DELAY FOR DATA REQUEST
  5542                              <1> 
  5543                              <1> HF_FAIL 	EQU	08H		; CMOS FLAG IN BYTE 0EH
  5544                              <1> 
  5545                              <1> ;-----		COMMAND BLOCK REFERENCE
  5546                              <1> 
  5547                              <1> ;CMD_BLOCK      EQU     BP-8            ; @CMD_BLOCK REFERENCES BLOCK HEAD IN SS
  5548                              <1> 					;  (BP) POINTS TO COMMAND BLOCK TAIL
  5549                              <1> 					;	AS DEFINED BY THE "ENTER" PARMS
  5550                              <1> ; 19/12/2014
  5551                              <1> ORG_VECTOR	equ	4*13h		; INT 13h vector
  5552                              <1> DISK_VECTOR	equ	4*40h		; INT 40h vector (for floppy disks)
  5553                              <1> ;HDISK_INT	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5554                              <1> ;HDISK_INT1	equ	4*76h		; Primary HDC - Hardware interrupt (IRQ14)
  5555                              <1> ;HDISK_INT2	equ	4*77h		; Secondary HDC - Hardware interrupt (IRQ15)
  5556                              <1> ;HF_TBL_VEC	equ	4*41h		; Pointer to 1st fixed disk parameter table
  5557                              <1> ;HF1_TBL_VEC	equ	4*46h		; Pointer to 2nd fixed disk parameter table
  5558                              <1> 
  5559                              <1> align 2
  5560                              <1> 
  5561                              <1> ;----------------------------------------------------------------
  5562                              <1> ; FIXED DISK I/O SETUP						:
  5563                              <1> ;								:
  5564                              <1> ;  -  ESTABLISH TRANSFER VECTORS FOR THE FIXED DISK		:
  5565                              <1> ;  -  PERFORM POWER ON DIAGNOSTICS				:
  5566                              <1> ;     SHOULD AN ERROR OCCUR A "1701" MESSAGE IS DISPLAYED       :
  5567                              <1> ;								:
  5568                              <1> ;----------------------------------------------------------------
  5569                              <1> 
  5570                              <1> DISK_SETUP:
  5571                              <1> 	;CLI
  5572                              <1> 	;;MOV	AX,ABS0 			; GET ABSOLUTE SEGMENT
  5573                              <1> 	;xor	ax,ax
  5574                              <1> 	;MOV	DS,AX				; SET SEGMENT REGISTER
  5575                              <1> 	;MOV	AX, [ORG_VECTOR] 		; GET DISKETTE VECTOR
  5576                              <1> 	;MOV	[DISK_VECTOR],AX		;  INTO INT 40H
  5577                              <1> 	;MOV	AX, [ORG_VECTOR+2]
  5578                              <1> 	;MOV	[DISK_VECTOR+2],AX
  5579                              <1> 	;MOV	word [ORG_VECTOR],DISK_IO	; FIXED DISK HANDLER
  5580                              <1> 	;MOV	[ORG_VECTOR+2],CS
  5581                              <1> 	; 1st controller (primary master, slave)   - IRQ 14
  5582                              <1> 	;;MOV	word [HDISK_INT],HD_INT		; FIXED DISK INTERRUPT
  5583                              <1> 	;mov	word [HDISK_INT1],HD_INT	;
  5584                              <1> 	;;MOV	[HDISK_INT+2],CS
  5585                              <1> 	;mov	[HDISK_INT1+2],CS
  5586                              <1> 	; 2nd controller (secondary master, slave) - IRQ 15
  5587                              <1> 	;mov	word [HDISK_INT2],HD1_INT	;
  5588                              <1> 	;mov	[HDISK_INT2+2],CS
  5589                              <1> 	;
  5590                              <1> 	;;MOV	word [HF_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80
  5591                              <1> 	;;MOV	word [HF_TBL_VEC+2],DPT_SEGM
  5592                              <1> 	;;MOV	word [HF1_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81
  5593                              <1> 	;;MOV	word [HF1_TBL_VEC+2],DPT_SEGM
  5594                              <1> 	;push	cs
  5595                              <1> 	;pop	ds
  5596                              <1> 	;mov	word [HDPM_TBL_VEC],HD0_DPT	; PARM TABLE DRIVE 80h
  5597                              <1> 	;mov	word [HDPM_TBL_VEC+2],DPT_SEGM
  5598 000025A4 C705[746B0000]0000- <1> 	mov 	dword [HDPM_TBL_VEC], (DPT_SEGM*16)+HD0_DPT
  5598 000025AC 0900                <1>
  5599                              <1> 	;mov	word [HDPS_TBL_VEC],HD1_DPT	; PARM TABLE DRIVE 81h
  5600                              <1> 	;mov	word [HDPS_TBL_VEC+2],DPT_SEGM
  5601 000025AE C705[786B0000]2000- <1> 	mov 	dword [HDPS_TBL_VEC], (DPT_SEGM*16)+HD1_DPT
  5601 000025B6 0900                <1>
  5602                              <1> 	;mov	word [HDSM_TBL_VEC],HD2_DPT	; PARM TABLE DRIVE 82h
  5603                              <1> 	;mov	word [HDSM_TBL_VEC+2],DPT_SEGM
  5604 000025B8 C705[7C6B0000]4000- <1> 	mov 	dword [HDSM_TBL_VEC], (DPT_SEGM*16)+HD2_DPT
  5604 000025C0 0900                <1>
  5605                              <1> 	;mov	word [HDSS_TBL_VEC],HD3_DPT	; PARM TABLE DRIVE 83h
  5606                              <1> 	;mov	word [HDSS_TBL_VEC+2],DPT_SEGM
  5607 000025C2 C705[806B0000]6000- <1> 	mov 	dword [HDSS_TBL_VEC], (DPT_SEGM*16)+HD3_DPT
  5607 000025CA 0900                <1>
  5608                              <1> 	;
  5609                              <1> 	;;IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  5610                              <1> 	;;;AND	AL,0BFH
  5611                              <1> 	;;and	al, 3Fh			; enable IRQ 14 and IRQ 15
  5612                              <1> 	;;;JMP	$+2
  5613                              <1> 	;;IODELAY
  5614                              <1> 	;;OUT	INTB01,AL
  5615                              <1> 	;;IODELAY
  5616                              <1> 	;;IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  5617                              <1> 	;;AND	AL,0FBH 		;  SECOND CHIP
  5618                              <1> 	;;;JMP	$+2
  5619                              <1> 	;;IODELAY
  5620                              <1> 	;;OUT	INTA01,AL
  5621                              <1> 	;
  5622                              <1> 	;STI
  5623                              <1> 	;;PUSH	DS			; MOVE ABS0 POINTER TO
  5624                              <1> 	;;POP	ES			; EXTRA SEGMENT POINTER
  5625                              <1> 	;;;CALL	DDS			; ESTABLISH DATA SEGMENT
  5626                              <1> 	;;MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5627                              <1> 	;;MOV	byte [HF_NUM],0		; ZERO NUMBER OF FIXED DISKS
  5628                              <1> 	;;MOV	byte [CONTROL_BYTE],0
  5629                              <1> 	;;MOV	byte [PORT_OFF],0	; ZERO CARD OFFSET
  5630                              <1> 	; 20/12/2014 - private code by Erdogan Tan
  5631                              <1> 		      ; (out of original PC-AT, PC-XT BIOS code)
  5632                              <1> 	;mov	si, hd0_type
  5633 000025CC BE[D0650000]        <1> 	mov	esi, hd0_type
  5634                              <1> 	;mov	cx, 4
  5635 000025D1 B904000000          <1> 	mov	ecx, 4
  5636                              <1> hde_l:
  5637 000025D6 AC                  <1> 	lodsb
  5638 000025D7 3C80                <1> 	cmp	al, 80h			; 8?h = existing
  5639 000025D9 7206                <1> 	jb	short _L4
  5640 000025DB FE05[706B0000]      <1> 	inc	byte [HF_NUM]		; + 1 hard (fixed) disk drives
  5641                              <1> _L4: ; 26/02/2015
  5642 000025E1 E2F3                <1> 	loop	hde_l	
  5643                              <1> ;_L4:					; 0 <= [HF_NUM] =< 4
  5644                              <1> ;L4:
  5645                              <1> 	; 
  5646                              <1> 	;; 31/12/2014 - cancel controller diagnostics here
  5647                              <1> 	;;;mov 	cx, 3  ; 26/12/2014 (Award BIOS 1999)
  5648                              <1> 	;;mov 	cl, 3
  5649                              <1> 	;;
  5650                              <1> 	;;MOV	DL,80H			; CHECK THE CONTROLLER
  5651                              <1> ;;hdc_dl:
  5652                              <1> 	;;MOV	AH,14H			; USE CONTROLLER DIAGNOSTIC COMMAND
  5653                              <1> 	;;INT	13H			; CALL BIOS WITH DIAGNOSTIC COMMAND
  5654                              <1> 	;;;JC	short CTL_ERRX		; DISPLAY ERROR MESSAGE IF BAD RETURN
  5655                              <1> 	;;;jc	short POD_DONE ;22/12/2014
  5656                              <1> 	;;jnc	short hdc_reset0
  5657                              <1> 	;;loop	hdc_dl
  5658                              <1> 	;;; 27/12/2014
  5659                              <1> 	;;stc
  5660                              <1> 	;;retn
  5661                              <1> 	;
  5662                              <1> ;;hdc_reset0:
  5663                              <1> 	; 18/01/2015
  5664 000025E3 8A0D[706B0000]      <1> 	mov	cl, [HF_NUM]
  5665 000025E9 20C9                <1> 	and	cl, cl
  5666 000025EB 740D                <1> 	jz	short POD_DONE
  5667                              <1> 	;
  5668 000025ED B27F                <1> 	mov	dl, 7Fh
  5669                              <1> hdc_reset1:
  5670 000025EF FEC2                <1> 	inc	dl
  5671                              <1> 	;; 31/12/2015
  5672                              <1> 	;;push	dx
  5673                              <1> 	;;push	cx
  5674                              <1> 	;;push	ds
  5675                              <1> 	;;sub	ax, ax
  5676                              <1> 	;;mov	ds, ax
  5677                              <1> 	;;MOV	AX, [TIMER_LOW]		; GET START TIMER COUNTS
  5678                              <1> 	;;pop	ds
  5679                              <1> 	;;MOV	BX,AX
  5680                              <1> 	;;ADD	AX,6*182		; 60 SECONDS* 18.2
  5681                              <1> 	;;MOV	CX,AX
  5682                              <1> 	;;mov	word [wait_count], 0	; 22/12/2014 (reset wait counter)
  5683                              <1> 	;;
  5684                              <1> 	;; 31/12/2014 - cancel HD_RESET_1
  5685                              <1> 	;;CALL	HD_RESET_1		; SET UP DRIVE 0, (1,2,3)
  5686                              <1> 	;;pop	cx
  5687                              <1> 	;;pop	dx
  5688                              <1> 	;;
  5689                              <1> 	; 18/01/2015
  5690 000025F1 B40D                <1> 	mov	ah, 0Dh ; ALTERNATE RESET
  5691                              <1> 	;int	13h
  5692 000025F3 E8A4FFFFFF          <1> 	call	int13h
  5693 000025F8 E2F5                <1> 	loop	hdc_reset1
  5694                              <1> POD_DONE:
  5695 000025FA C3                  <1> 	RETn
  5696                              <1> 
  5697                              <1> ;;-----	POD_ERROR
  5698                              <1> 
  5699                              <1> ;;CTL_ERRX:
  5700                              <1> ;	;MOV	SI,OFFSET F1782 	; CONTROLLER ERROR
  5701                              <1> ;	;CALL	SET_FAIL		; DO NOT IPL FROM DISK
  5702                              <1> ;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5703                              <1> ;	;JMP	short POD_DONE
  5704                              <1> 
  5705                              <1> ;;HD_RESET_1:
  5706                              <1> ;;	;PUSH	BX			; SAVE TIMER LIMITS
  5707                              <1> ;;	;PUSH	CX
  5708                              <1> ;;RES_1: MOV	AH,09H			; SET DRIVE PARAMETERS
  5709                              <1> ;;	INT	13H
  5710                              <1> ;;	JC	short RES_2
  5711                              <1> ;;	MOV	AH,11H			; RECALIBRATE DRIVE
  5712                              <1> ;;	INT	13H
  5713                              <1> ;;	JNC	short RES_CK		; DRIVE OK
  5714                              <1> ;;RES_2: ;CALL	POD_TCHK		; CHECK TIME OUT
  5715                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5716                              <1> ;;					; (30 seconds)		
  5717                              <1> ;;	;cmc
  5718                              <1> ;;	;JNC	short RES_1
  5719                              <1> ;;	jb	short RES_1
  5720                              <1> ;;;RES_FL: ;MOV	SI,OFFSET F1781 	; INDICATE DISK 1 FAILURE;
  5721                              <1> ;;	;TEST	DL,1
  5722                              <1> ;;	;JNZ	RES_E1
  5723                              <1> ;;	;MOV	SI,OFFSET F1780 	; INDICATE DISK 0 FAILURE
  5724                              <1> ;;	;CALL	SET_FAIL		; DO NOT TRY TO IPL DISK 0
  5725                              <1> ;;	;JMP	SHORT RES_E1
  5726                              <1> ;;RES_ER: ; 22/12/2014
  5727                              <1> ;;RES_OK:
  5728                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5729                              <1> ;;	;POP	BX
  5730                              <1> ;;	RETn
  5731                              <1> ;;
  5732                              <1> ;;RES_RS: MOV	AH,00H			; RESET THE DRIVE
  5733                              <1> ;;	INT	13H
  5734                              <1> ;;RES_CK: MOV	AH,08H			; GET MAX CYLINDER,HEAD,SECTOR
  5735                              <1> ;;	MOV	BL,DL			; SAVE DRIVE CODE
  5736                              <1> ;;	INT	13H
  5737                              <1> ;;	JC	short RES_ER
  5738                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE MAX CYLINDER, SECTOR
  5739                              <1> ;;	MOV	DL,BL			; RESTORE DRIVE CODE
  5740                              <1> ;;RES_3: MOV	AX,0401H		; VERIFY THE LAST SECTOR
  5741                              <1> ;;	INT	13H
  5742                              <1> ;;	JNC	short RES_OK		; VERIFY OK
  5743                              <1> ;;	CMP	AH,BAD_SECTOR		; OK ALSO IF JUST ID READ
  5744                              <1> ;;	JE	short RES_OK
  5745                              <1> ;;	CMP	AH,DATA_CORRECTED
  5746                              <1> ;;	JE	short RES_OK
  5747                              <1> ;;	CMP	AH,BAD_ECC
  5748                              <1> ;;	JE	short RES_OK
  5749                              <1> ;;	;CALL	POD_TCHK		; CHECK FOR TIME OUT
  5750                              <1> ;;	cmp	word [wait_count], 6*182 ; waiting time (in timer ticks)
  5751                              <1> ;;					; (60 seconds)		
  5752                              <1> ;;	cmc
  5753                              <1> ;;	JC	short RES_ER		; FAILED
  5754                              <1> ;;	MOV	CX,[NEC_STATUS] 	; GET SECTOR ADDRESS, AND CYLINDER
  5755                              <1> ;;	MOV	AL,CL			; SEPARATE OUT SECTOR NUMBER
  5756                              <1> ;;	AND	AL,3FH
  5757                              <1> ;;	DEC	AL			; TRY PREVIOUS ONE
  5758                              <1> ;;	JZ	short RES_RS		; WE'VE TRIED ALL SECTORS ON TRACK
  5759                              <1> ;;	AND	CL,0C0H 		; KEEP CYLINDER BITS
  5760                              <1> ;;	OR	CL,AL			; MERGE SECTOR WITH CYLINDER BITS
  5761                              <1> ;;	MOV	[NEC_STATUS],CX 	; SAVE CYLINDER, NEW SECTOR NUMBER
  5762                              <1> ;;	JMP	short RES_3		; TRY AGAIN
  5763                              <1> ;;;RES_ER: MOV	SI,OFFSET F1791 	; INDICATE DISK 1 ERROR
  5764                              <1> ;;	;TEST	DL,1
  5765                              <1> ;;	;JNZ	short RES_E1
  5766                              <1> ;;	;MOV	SI,OFFSET F1790 	; INDICATE DISK 0 ERROR
  5767                              <1> ;;;RES_E1:
  5768                              <1> ;;	;CALL	E_MSG			; DISPLAY ERROR AND SET (BP) ERROR FLAG
  5769                              <1> ;;;RES_OK:
  5770                              <1> ;;	;POP	CX			; RESTORE TIMER LIMITS
  5771                              <1> ;;	;POP	BX
  5772                              <1> ;;	;RETn
  5773                              <1> ;
  5774                              <1> ;;SET_FAIL:
  5775                              <1> ;	;MOV	AX,X*(CMOS_DIAG+NMI)	; GET CMOS ERROR BYTE
  5776                              <1> ;	;CALL	CMOS_READ
  5777                              <1> ;	;OR	AL,HF_FAIL		; SET DO NOT IPL FROM DISK FLAG
  5778                              <1> ;	;XCHG	AH,AL			; SAVE IT
  5779                              <1> ;	;CALL	CMOS_WRITE		; PUT IT OUT
  5780                              <1> ;	;RETn
  5781                              <1> ;
  5782                              <1> ;;POD_TCHK:				; CHECK FOR 30 SECOND TIME OUT
  5783                              <1> ;	;POP	AX			; SAVE RETURN
  5784                              <1> ;	;POP	CX			; GET TIME OUT LIMITS
  5785                              <1> ;	;POP	BX
  5786                              <1> ;	;PUSH	BX			; AND SAVE THEM AGAIN
  5787                              <1> ;	;PUSH	CX
  5788                              <1> ;	;PUSH	AX
  5789                              <1> ;	;push	ds
  5790                              <1> ;	;xor	ax, ax
  5791                              <1> ;	;mov	ds, ax			; RESTORE RETURN
  5792                              <1> ;	;MOV	AX, [TIMER_LOW]		; AX = CURRENT TIME
  5793                              <1> ;	;				; BX = START TIME
  5794                              <1> ;	;				; CX = END TIME
  5795                              <1> ;	;pop	ds
  5796                              <1> ;	;CMP	BX,CX
  5797                              <1> ;	;JB	short TCHK1		; START < END
  5798                              <1> ;	;CMP	BX,AX
  5799                              <1> ;	;JB	short TCHKG		; END < START < CURRENT
  5800                              <1> ;	;JMP	SHORT TCHK2		; END, CURRENT < START
  5801                              <1> ;;TCHK1: CMP	AX,BX
  5802                              <1> ;;	JB	short TCHKNG		; CURRENT < START < END
  5803                              <1> ;;TCHK2: CMP	AX,CX
  5804                              <1> ;;	JB	short TCHKG		; START < CURRENT < END
  5805                              <1> ;;					; OR CURRENT < END < START
  5806                              <1> ;;TCHKNG: STC				; CARRY SET INDICATES TIME OUT
  5807                              <1> ;;	RETn
  5808                              <1> ;;TCHKG: CLC				; INDICATE STILL TIME
  5809                              <1> ;;	RETn
  5810                              <1> ;;
  5811                              <1> ;;int_13h:
  5812                              <1> 
  5813                              <1> ;----------------------------------------
  5814                              <1> ;	FIXED DISK BIOS ENTRY POINT	:
  5815                              <1> ;----------------------------------------
  5816                              <1> 
  5817                              <1> DISK_IO:
  5818 000025FB 80FA80              <1> 	CMP	DL,80H			; TEST FOR FIXED DISK DRIVE
  5819                              <1> 	;JAE	short A1		; YES, HANDLE HERE
  5820                              <1> 	;;;INT	40H			; DISKETTE HANDLER
  5821                              <1> 	;;call	int40h
  5822                              <1> 	;jb	DISKETTE_IO_1
  5823                              <1> 	; 24/12/2021
  5824 000025FE 7305                <1> 	jnb	short A1
  5825 00002600 E960F1FFFF          <1> 	jmp	DISKETTE_IO_1
  5826                              <1> ;RET_2:
  5827                              <1> 	;RETf	2			; BACK TO CALLER
  5828                              <1> ;	retf	4
  5829                              <1> A1:
  5830 00002605 FB                  <1> 	STI				; ENABLE INTERRUPTS
  5831                              <1> 	;; 04/01/2015
  5832                              <1> 	;;OR	AH,AH
  5833                              <1> 	;;JNZ	short A2
  5834                              <1> 	;;INT	40H			; RESET NEC WHEN AH=0
  5835                              <1> 	;;SUB	AH,AH
  5836 00002606 80FA83              <1> 	CMP	DL,(80H + S_MAX_FILE - 1)
  5837 00002609 772E                <1> 	JA	short RET_2
  5838                              <1> 	; 18/01/2015
  5839 0000260B 08E4                <1> 	or	ah,ah
  5840 0000260D 742D                <1> 	jz	short A4
  5841 0000260F 80FC0D              <1> 	cmp	ah, 0Dh	; Alternate reset
  5842 00002612 7504                <1> 	jne	short A2
  5843 00002614 28E4                <1> 	sub	ah,ah	; Reset
  5844 00002616 EB24                <1> 	jmp	short A4
  5845                              <1> A2:
  5846 00002618 80FC08              <1> 	CMP	AH,08H			; GET PARAMETERS IS A SPECIAL CASE
  5847                              <1> 	;JNZ	short A3
  5848                              <1>         ;JMP    GET_PARM_N
  5849                              <1> 	;je	GET_PARM_N
  5850                              <1> 	; 24/12/2021
  5851 0000261B 7505                <1> 	jne	short A3
  5852 0000261D E90D030000          <1> 	jmp	GET_PARM_N
  5853                              <1> A3:	
  5854 00002622 80FC15              <1> 	CMP	AH,15H			; READ DASD TYPE IS ALSO
  5855                              <1> 	;JNZ	short A4
  5856                              <1>         ;JMP    READ_DASD_TYPE
  5857                              <1> 	;je	READ_DASD_TYPE
  5858                              <1> 	; 24/12/2021
  5859 00002625 7505                <1> 	jne	short A3_A4
  5860 00002627 E9BA020000          <1> 	jmp	READ_DASD_TYPE
  5861                              <1> A3_A4:
  5862                              <1> 	; 02/02/2015
  5863 0000262C 80FC1D              <1> 	cmp	ah, 1Dh			; (Temporary for Retro UNIX 386 v1)
  5864                              <1> 	; 12/01/2015
  5865 0000262F F5                  <1> 	cmc
  5866 00002630 730A                <1> 	jnc	short A4
  5867                              <1> 	; 30/01/2015
  5868                              <1> 	;mov	byte [CS:DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  5869 00002632 C605[6F6B0000]01    <1>         mov     byte [DISK_STATUS1], BAD_CMD
  5870                              <1> 	;jmp	short RET_2
  5871                              <1> RET_2:
  5872 00002639 CA0400              <1> 	retf	4
  5873                              <1> A4:					; SAVE REGISTERS DURING OPERATION
  5874 0000263C C8080000            <1> 	ENTER	8,0			; SAVE (BP) AND MAKE ROOM FOR @CMD_BLOCK
  5875 00002640 53                  <1> 	PUSH	eBX			;  IN THE STACK, THE COMMAND BLOCK IS:
  5876 00002641 51                  <1> 	PUSH	eCX			;   @CMD_BLOCK == BYTE PTR [BP]-8
  5877 00002642 52                  <1> 	PUSH	eDX
  5878 00002643 1E                  <1> 	PUSH	DS
  5879 00002644 06                  <1> 	PUSH	ES
  5880 00002645 56                  <1> 	PUSH	eSI
  5881 00002646 57                  <1> 	PUSH	eDI
  5882                              <1> 	;;04/01/2015
  5883                              <1> 	;;OR	AH,AH			; CHECK FOR RESET
  5884                              <1> 	;;JNZ	short A5
  5885                              <1> 	;;MOV	DL,80H			; FORCE DRIVE 80 FOR RESET
  5886                              <1> ;;A5:	
  5887                              <1> 	;push	cs
  5888                              <1> 	;pop	ds
  5889                              <1> 	; 21/02/2015
  5890                              <1> 	;push	ax
  5891                              <1> 	; 24/12/2021
  5892 00002647 50                  <1> 	push	eax
  5893 00002648 66B81000            <1> 	mov	ax, KDATA
  5894 0000264C 8ED8                <1> 	mov	ds, ax
  5895 0000264E 8EC0                <1> 	mov	es, ax	
  5896                              <1> 	;pop	ax
  5897                              <1> 	; 24/12/2021
  5898 00002650 58                  <1> 	pop	eax
  5899 00002651 E889000000          <1> 	CALL	DISK_IO_CONT		; PERFORM THE OPERATION
  5900                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5901 00002656 8A25[6F6B0000]      <1> 	MOV	AH,[DISK_STATUS1]	; GET STATUS FROM OPERATION
  5902 0000265C 80FC01              <1> 	CMP	AH,1			; SET THE CARRY FLAG TO INDICATE
  5903 0000265F F5                  <1> 	CMC				; SUCCESS OR FAILURE
  5904 00002660 5F                  <1> 	POP	eDI			; RESTORE REGISTERS
  5905 00002661 5E                  <1> 	POP	eSI
  5906 00002662 07                  <1>         POP     ES
  5907 00002663 1F                  <1>         POP     DS
  5908 00002664 5A                  <1> 	POP	eDX
  5909 00002665 59                  <1> 	POP	eCX
  5910 00002666 5B                  <1> 	POP	eBX
  5911 00002667 C9                  <1> 	LEAVE				; ADJUST (SP) AND RESTORE (BP)
  5912                              <1> 	;RETf	2			; THROW AWAY SAVED FLAGS
  5913 00002668 CA0400              <1> 	retf	4
  5914                              <1> ; 21/02/2015
  5915                              <1> ;       dw --> dd
  5916                              <1> M1:					; FUNCTION TRANSFER TABLE
  5917 0000266B [24280000]          <1> 	dd	DISK_RESET		; 000H
  5918 0000266F [99280000]          <1> 	dd	RETURN_STATUS		; 001H
  5919 00002673 [A6280000]          <1> 	dd	DISK_READ		; 002H
  5920 00002677 [AF280000]          <1> 	dd	DISK_WRITE		; 003H
  5921 0000267B [B8280000]          <1> 	dd	DISK_VERF		; 004H
  5922 0000267F [D0280000]          <1> 	dd	FMT_TRK 		; 005H
  5923 00002683 [1A280000]          <1> 	dd	BAD_COMMAND		; 006H	FORMAT BAD SECTORS
  5924 00002687 [1A280000]          <1> 	dd	BAD_COMMAND		; 007H	FORMAT DRIVE
  5925 0000268B [1A280000]          <1> 	dd	BAD_COMMAND		; 008H	RETURN PARAMETERS
  5926 0000268F [91290000]          <1> 	dd	INIT_DRV		; 009H
  5927 00002693 [F0290000]          <1> 	dd	RD_LONG 		; 00AH
  5928 00002697 [F9290000]          <1> 	dd	WR_LONG 		; 00BH
  5929 0000269B [022A0000]          <1> 	dd	DISK_SEEK		; 00CH
  5930 0000269F [24280000]          <1> 	dd	DISK_RESET		; 00DH
  5931 000026A3 [1A280000]          <1> 	dd	BAD_COMMAND		; 00EH	READ BUFFER
  5932 000026A7 [1A280000]          <1> 	dd	BAD_COMMAND		; 00FH	WRITE BUFFER
  5933 000026AB [2A2A0000]          <1> 	dd	TST_RDY 		; 010H
  5934 000026AF [4E2A0000]          <1> 	dd	HDISK_RECAL		; 011H
  5935 000026B3 [1A280000]          <1> 	dd	BAD_COMMAND		; 012H	MEMORY DIAGNOSTIC
  5936 000026B7 [1A280000]          <1> 	dd	BAD_COMMAND		; 013H	DRIVE DIAGNOSTIC
  5937 000026BB [842A0000]          <1> 	dd	CTLR_DIAGNOSTIC 	; 014H	CONTROLLER DIAGNOSTIC
  5938                              <1> 	; 02/02/2015 (Temporary - Retro UNIX 386 v1 - DISK I/O test)
  5939 000026BF [1A280000]          <1> 	dd	BAD_COMMAND		; 015h
  5940 000026C3 [1A280000]          <1> 	dd	BAD_COMMAND		; 016h
  5941 000026C7 [1A280000]          <1> 	dd	BAD_COMMAND		; 017h
  5942 000026CB [1A280000]          <1> 	dd	BAD_COMMAND		; 018h
  5943 000026CF [1A280000]          <1> 	dd	BAD_COMMAND		; 019h
  5944 000026D3 [1A280000]          <1> 	dd	BAD_COMMAND		; 01Ah
  5945 000026D7 [A6280000]          <1> 	dd	DISK_READ		; 01Bh ; LBA read
  5946 000026DB [AF280000]          <1> 	dd	DISK_WRITE		; 01Ch ; LBA write
  5947                              <1> M1L     EQU    $-M1
  5948                              <1> 
  5949                              <1> DISK_IO_CONT:
  5950                              <1> 	;;CALL	DDS			; ESTABLISH SEGMENT
  5951 000026DF 80FC01              <1> 	CMP	AH,01H			; RETURN STATUS
  5952                              <1> 	;;JNZ	short SU0
  5953                              <1>         ;;JMP	RETURN_STATUS
  5954                              <1> 	;je	RETURN_STATUS
  5955                              <1> 	; 24/12/2021
  5956 000026E2 7505                <1> 	jne	short SU0
  5957 000026E4 E9B0010000          <1> 	jmp	RETURN_STATUS
  5958                              <1> SU0:
  5959 000026E9 C605[6F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; RESET THE STATUS INDICATOR
  5960                              <1> 	;;PUSH	BX			; SAVE DATA ADDRESS
  5961                              <1> 	;mov	si, bx ;; 14/02/2015
  5962 000026F0 89DE                <1> 	mov	esi, ebx ; 21/02/2015
  5963 000026F2 8A1D[706B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  5964                              <1> 	;; 04/01/2015
  5965                              <1> 	;;PUSH	AX
  5966 000026F8 80E27F              <1> 	AND	DL,7FH			; GET DRIVE AS 0 OR 1
  5967                              <1> 					; (get drive number as 0 to 3)
  5968 000026FB 38D3                <1> 	CMP	BL,DL
  5969                              <1>         ;;JBE   BAD_COMMAND_POP         ; INVALID DRIVE
  5970                              <1>         ;jbe    BAD_COMMAND ;; 14/02/2015
  5971                              <1> 	; 24/12/2021
  5972 000026FD 7705                <1> 	ja	short su0_su1
  5973 000026FF E916010000          <1> 	jmp	BAD_COMMAND
  5974                              <1> su0_su1:
  5975                              <1>         ;;03/01/2015
  5976 00002704 29DB                <1> 	sub	ebx, ebx
  5977 00002706 88D3                <1> 	mov	bl, dl
  5978                              <1> 	;sub	bh, bh
  5979 00002708 883D[846B0000]      <1> 	mov	[LBAMode], bh 	; 0
  5980                              <1> 	;;test	byte [bx+hd0_type], 1	; LBA ready ?
  5981                              <1> 	;test	byte [ebx+hd0_type], 1
  5982                              <1> 	;jz	short su1		; no
  5983                              <1> 	;inc	byte [LBAMode]
  5984                              <1> ;su1:
  5985                              <1> 	; 21/02/2015 (32 bit modification)
  5986                              <1> 	; 04/01/2015
  5987                              <1> 	;push	ax ; ***
  5988                              <1> 	; 24/12/2021
  5989 0000270E 50                  <1> 	push	eax ; ***
  5990                              <1> 	;PUSH	ES ; **
  5991                              <1> 	;PUSH	DX ; *
  5992                              <1> 	; 24/12/2021
  5993 0000270F 52                  <1> 	push	edx ; *
  5994                              <1> 	;push	ax
  5995 00002710 50                  <1> 	push	eax
  5996 00002711 E849060000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS
  5997                              <1> 	; 02/02/2015
  5998                              <1> 	;mov	ax, [ES:BX+16] ; I/O port base address (1F0h, 170h)
  5999 00002716 668B4310            <1> 	mov	ax, [ebx+16]
  6000 0000271A 66A3[C4650000]      <1> 	mov	[HF_PORT], ax
  6001                              <1> 	;mov	dx, [ES:BX+18] ; control port address (3F6h, 376h)
  6002 00002720 668B5312            <1> 	mov	dx, [ebx+18]
  6003 00002724 668915[C6650000]    <1> 	mov	[HF_REG_PORT], dx
  6004                              <1> 	;mov	al, [ES:BX+20] ; head register upper nibble (A0h,B0h,E0h,F0h)
  6005 0000272B 8A4314              <1> 	mov	al, [ebx+20]
  6006                              <1> 	; 23/02/2015
  6007 0000272E A840                <1> 	test	al, 40h	 ; LBA bit (bit 6)
  6008 00002730 7406                <1> 	jz 	short su1
  6009 00002732 FE05[846B0000]      <1> 	inc	byte [LBAMode] ; 1 
  6010                              <1> su1: 	 
  6011 00002738 C0E804              <1> 	shr 	al, 4
  6012 0000273B 2401                <1> 	and	al, 1			
  6013 0000273D A2[C8650000]        <1> 	mov	[hf_m_s], al 
  6014                              <1> 	;
  6015                              <1> 	; 03/01/2015
  6016                              <1> 	;MOV	AL,byte [ES:BX+8]	; GET CONTROL BYTE MODIFIER
  6017 00002742 8A4308              <1> 	mov	al, [ebx+8]
  6018                              <1> 	;MOV	DX,[HF_REG_PORT]	; Device Control register	
  6019 00002745 EE                  <1> 	OUT	DX,AL			; SET EXTRA HEAD OPTION
  6020                              <1> 					; Control Byte:  (= 08h, here)
  6021                              <1> 					; bit 0 - 0
  6022                              <1> 					; bit 1 - nIEN (1 = disable irq)
  6023                              <1> 					; bit 2 - SRST (software RESET)
  6024                              <1> 					; bit 3 - use extra heads (8 to 15)
  6025                              <1> 					;         -always set to 1-	
  6026                              <1> 					; (bits 3 to 7 are reserved
  6027                              <1> 					;          for ATA devices)
  6028 00002746 8A25[716B0000]      <1> 	MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6029 0000274C 80E4C0              <1> 	AND	AH,0C0H 		; CONTROL BYTE
  6030 0000274F 08C4                <1> 	OR	AH,AL
  6031 00002751 8825[716B0000]      <1> 	MOV	[CONTROL_BYTE],AH	
  6032                              <1> 	; 04/01/2015
  6033                              <1> 	;pop	ax
  6034                              <1> 	; 24/12/2021
  6035 00002757 58                  <1> 	pop	eax
  6036                              <1> 	;pop	dx ; * ;; 14/02/2015
  6037                              <1> 	; 24/12/2021
  6038 00002758 5A                  <1> 	pop	edx ; *
  6039 00002759 20E4                <1> 	and	ah, ah	; Reset function ?
  6040 0000275B 7506                <1> 	jnz	short su2
  6041                              <1> 	;;pop	dx ; * ;; 14/02/2015
  6042                              <1> 	;pop	es ; **
  6043                              <1> 	;pop	ax ; ***
  6044                              <1> 	; 24/12/2021
  6045 0000275D 58                  <1> 	pop	eax ; ***	
  6046                              <1> 	;;pop	bx
  6047 0000275E E9C1000000          <1>         jmp     DISK_RESET
  6048                              <1> su2:
  6049 00002763 803D[846B0000]00    <1> 	cmp	byte [LBAMode], 0
  6050 0000276A 765E                <1> 	jna	short su3
  6051                              <1> 	;
  6052                              <1> 	; 02/02/2015 (LBA read/write function calls)
  6053 0000276C 80FC1B              <1> 	cmp	ah, 1Bh
  6054 0000276F 720B                <1> 	jb	short lbarw1
  6055 00002771 80FC1C              <1> 	cmp	ah, 1Ch
  6056 00002774 7759                <1> 	ja 	short invldfnc
  6057                              <1> 	;;pop	dx ; * ; 14/02/2015
  6058                              <1> 	;mov	ax, cx ; Lower word of LBA address (bits 0-15)
  6059 00002776 89C8                <1> 	mov	eax, ecx ; LBA address (21/02/2015)
  6060                              <1> 	;; 14/02/2015
  6061 00002778 88D1                <1> 	mov	cl, dl ; 14/02/2015
  6062                              <1> 	;;mov	dx, bx
  6063                              <1> 	;mov	dx, si ; higher word of LBA address (bits 16-23)
  6064                              <1> 	;;mov	bx, di
  6065                              <1> 	;mov	si, di ; Buffer offset
  6066 0000277A EB2E                <1> 	jmp	short lbarw2
  6067                              <1> lbarw1:
  6068                              <1> 	; convert CHS to LBA
  6069                              <1> 	;
  6070                              <1> 	; LBA calculation - AWARD BIOS - 1999 - AHDSK.ASM
  6071                              <1> 	; LBA = "# of Heads" * Sectors/Track * Cylinder + Head * Sectors/Track
  6072                              <1> 	;	+ Sector - 1
  6073                              <1> 	;push	dx ; * ;; 14/02/2015
  6074                              <1> 	; 24/12/2021
  6075 0000277C 52                  <1> 	push	edx ; *
  6076                              <1> 	;xor	dh, dh
  6077 0000277D 31D2                <1> 	xor	edx, edx
  6078                              <1> 	;mov	dl, [ES:BX+14]	; sectors per track (logical)
  6079 0000277F 8A530E              <1> 	mov	dl, [ebx+14]
  6080                              <1> 	;xor	ah, ah
  6081 00002782 31C0                <1> 	xor	eax, eax
  6082                              <1> 	;mov	al, [ES:BX+2]	; heads (logical) 	
  6083 00002784 8A4302              <1> 	mov	al, [ebx+2]
  6084 00002787 FEC8                <1> 	dec	al
  6085                              <1> 	;inc	ax		; 0 =  256
  6086 00002789 40                  <1> 	inc	eax ; 24/12/2021
  6087 0000278A 66F7E2              <1> 	mul 	dx
  6088                              <1> 		; AX = # of Heads" * Sectors/Track
  6089 0000278D 6689CA              <1> 	mov	dx, cx
  6090                              <1> 	;and	cx, 3Fh	 ; sector  (1 to 63)
  6091 00002790 83E13F              <1> 	and	ecx, 3fh
  6092 00002793 86D6                <1> 	xchg	dl, dh
  6093 00002795 C0EE06              <1> 	shr	dh, 6
  6094                              <1> 		; DX = cylinder (0 to 1023)
  6095                              <1> 	;mul 	dx
  6096                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder
  6097 00002798 F7E2                <1> 	mul	edx
  6098 0000279A FEC9                <1> 	dec	cl  ; sector - 1
  6099                              <1> 	;add	ax, cx
  6100                              <1> 	;adc	dx, 0
  6101                              <1> 		; DX:AX = # of Heads" * Sectors/Track * Cylinder + Sector -1
  6102 0000279C 01C8                <1> 	add	eax, ecx
  6103                              <1> 	;pop	cx ; * ; ch = head, cl = drive number (zero based)
  6104                              <1> 	; 24/12/2021
  6105 0000279E 59                  <1> 	pop	ecx ; * ; ch = head, cl = drive number (zero based)
  6106                              <1> 	;push	dx
  6107                              <1> 	;push	ax
  6108 0000279F 50                  <1> 	push	eax
  6109                              <1> 	;mov	al, [ES:BX+14]	; sectors per track (logical)	
  6110 000027A0 8A430E              <1> 	mov	al, [ebx+14]
  6111 000027A3 F6E5                <1> 	mul	ch
  6112                              <1> 		; AX = Head * Sectors/Track
  6113 000027A5 6699                <1>         cwd
  6114                              <1> 	;pop	dx
  6115 000027A7 5A                  <1> 	pop	edx
  6116                              <1> 	;add	ax, dx
  6117                              <1> 	;pop	dx
  6118                              <1> 	;adc	dx, 0 ; add carry bit
  6119 000027A8 01D0                <1> 	add	eax, edx
  6120                              <1> lbarw2:
  6121 000027AA 29D2                <1> 	sub	edx, edx ; 21/02/2015
  6122 000027AC 88CA                <1> 	mov	dl, cl ; 21/02/2015
  6123 000027AE C645F800            <1>         mov     byte [CMD_BLOCK], 0 ; Features Register
  6124                              <1> 				; NOTE: Features register (1F1h, 171h)
  6125                              <1> 				; is not used for ATA device R/W functions. 
  6126                              <1> 				; It is old/obsolete 'write precompensation'
  6127                              <1> 				; register and error register
  6128                              <1> 				; for old ATA/IDE devices.
  6129                              <1> 	; 18/01/2014
  6130                              <1> 	;mov	ch, [hf_m_s]	; Drive 0 (master) or 1 (slave)
  6131 000027B2 8A0D[C8650000]      <1> 	mov	cl, [hf_m_s]
  6132                              <1> 	;shl	ch, 4		; bit 4 (drive bit)
  6133                              <1> 	;or	ch, 0E0h	; bit 5 = 1
  6134                              <1> 				; bit 6 = 1 = LBA mode
  6135                              <1> 				; bit 7 = 1
  6136 000027B8 80C90E              <1> 	or	cl, 0Eh ; 1110b
  6137                              <1> 	;and	dh, 0Fh		; LBA byte 4 (bits 24 to 27)
  6138 000027BB 25FFFFFF0F          <1> 	and	eax, 0FFFFFFFh
  6139 000027C0 C1E11C              <1> 	shl	ecx, 28 ; 21/02/2015
  6140                              <1> 	;or	dh, ch
  6141 000027C3 09C8                <1> 	or	eax, ecx	
  6142                              <1> 	;;mov	[CMD_BLOCK+2], al ; LBA byte 1 (bits 0 to 7)
  6143                              <1> 				  ; (Sector Number Register)
  6144                              <1> 	;;mov	[CMD_BLOCK+3], ah ; LBA byte 2 (bits 8 to 15)
  6145                              <1> 				  ; (Cylinder Low Register)
  6146                              <1> 	;mov	[CMD_BLOCK+2], ax ; LBA byte 1, 2
  6147                              <1> 	;mov	[CMD_BLOCK+4], dl ; LBA byte 3 (bits 16 to 23)
  6148                              <1> 				  ; (Cylinder High Register)
  6149                              <1> 	;;mov	[CMD_BLOCK+5], dh ; LBA byte 4 (bits 24 to 27)
  6150                              <1> 				  ; (Drive/Head Register)
  6151                              <1> 	
  6152                              <1> 	;mov	[CMD_BLOCK+4], dx ; LBA byte 4, LBA & DEV select bits
  6153 000027C5 8945FA              <1> 	mov	[CMD_BLOCK+2], eax ; 21/02/2015
  6154                              <1> 	;14/02/2015
  6155                              <1> 	;mov	dl, cl ; Drive number (INIT_DRV)		
  6156 000027C8 EB37                <1> 	jmp	short su4
  6157                              <1> su3:
  6158                              <1> 	; 02/02/2015 
  6159                              <1> 	; (Temporary functions 1Bh & 1Ch are not valid for CHS mode) 
  6160 000027CA 80FC14              <1> 	cmp 	ah, 14h
  6161 000027CD 7603                <1> 	jna 	short chsfnc
  6162                              <1> invldfnc:
  6163                              <1>         ; 14/02/2015  
  6164                              <1> 	;pop	es ; **
  6165                              <1>         ;pop	ax ; ***
  6166                              <1>         ; 24/12/2021
  6167 000027CF 58                  <1> 	pop	eax ; ***
  6168                              <1> 	;jmp	short BAD_COMMAND_POP
  6169 000027D0 EB48                <1>         jmp     short BAD_COMMAND
  6170                              <1> chsfnc:	
  6171                              <1> 	;MOV	AX,[ES:BX+5]		; GET WRITE PRE-COMPENSATION CYLINDER
  6172 000027D2 668B4305            <1> 	mov	ax, [ebx+5]
  6173 000027D6 66C1E802            <1> 	SHR	AX,2
  6174 000027DA 8845F8              <1> 	MOV	[CMD_BLOCK],AL
  6175                              <1> 	;;MOV	AL,[ES:BX+8]		; GET CONTROL BYTE MODIFIER
  6176                              <1> 	;;PUSH	DX
  6177                              <1> 	;;MOV	DX,[HF_REG_PORT]
  6178                              <1> 	;;OUT	DX,AL			; SET EXTRA HEAD OPTION
  6179                              <1> 	;;POP	DX ; * 
  6180                              <1> 	;;POP	ES ; **
  6181                              <1> 	;;MOV	AH,[CONTROL_BYTE]	; SET EXTRA HEAD OPTION IN
  6182                              <1> 	;;AND	AH,0C0H 		; CONTROL BYTE	
  6183                              <1> 	;;OR	AH,AL
  6184                              <1> 	;;MOV	[CONTROL_BYTE],AH
  6185                              <1> 	;
  6186 000027DD 88C8                <1> 	MOV	AL,CL			; GET SECTOR NUMBER
  6187 000027DF 243F                <1> 	AND	AL,3FH
  6188 000027E1 8845FA              <1> 	MOV	[CMD_BLOCK+2],AL
  6189 000027E4 886DFB              <1> 	MOV	[CMD_BLOCK+3],CH 	; GET CYLINDER NUMBER
  6190 000027E7 88C8                <1> 	MOV	AL,CL
  6191 000027E9 C0E806              <1> 	SHR	AL,6
  6192 000027EC 8845FC              <1> 	MOV	[CMD_BLOCK+4],AL 	; CYLINDER HIGH ORDER 2 BITS
  6193                              <1> 	;;05/01/2015
  6194                              <1> 	;;MOV	AL,DL			; DRIVE NUMBER
  6195 000027EF A0[C8650000]        <1> 	mov	al, [hf_m_s]
  6196 000027F4 C0E004              <1> 	SHL	AL,4
  6197 000027F7 80E60F              <1> 	AND	DH,0FH			; HEAD NUMBER
  6198 000027FA 08F0                <1> 	OR	AL,DH
  6199                              <1> 	;OR	AL,80H or 20H
  6200 000027FC 0CA0                <1> 	OR	AL,80h+20h		; ECC AND 512 BYTE SECTORS
  6201 000027FE 8845FD              <1> 	MOV	[CMD_BLOCK+5],AL 	; ECC/SIZE/DRIVE/HEAD
  6202                              <1> su4:
  6203                              <1> 	;POP	ES ; **
  6204                              <1>         ;; 14/02/2015
  6205                              <1>         ;;POP   AX
  6206                              <1>         ;;MOV   [CMD_BLOCK+1],AL        ; SECTOR COUNT
  6207                              <1>         ;;PUSH  AX
  6208                              <1>         ;;MOV   AL,AH                   ; GET INTO LOW BYTE
  6209                              <1>         ;;XOR   AH,AH                   ; ZERO HIGH BYTE
  6210                              <1>         ;;SAL   AX,1                    ; *2 FOR TABLE LOOKUP
  6211                              <1> 	;pop     ax ; ***
  6212                              <1> 	; 24/12/2021
  6213 00002801 58                  <1> 	pop	eax ; ***
  6214 00002802 8845F9              <1> 	mov     [CMD_BLOCK+1], al
  6215 00002805 29DB                <1>         sub	ebx, ebx
  6216 00002807 88E3                <1> 	mov     bl, ah
  6217                              <1>         ;xor	bh, bh
  6218                              <1>         ;sal	bx, 1
  6219 00002809 66C1E302            <1>         sal	bx, 2	; 32 bit offset (21/02/2015)
  6220                              <1> 	;;MOV   SI,AX                   ; PUT INTO SI FOR BRANCH
  6221                              <1>         ;;CMP   AX,M1L                  ; TEST WITHIN RANGE
  6222                              <1>         ;;JNB   short BAD_COMMAND_POP
  6223                              <1>         ;cmp	bx, M1L
  6224 0000280D 83FB74              <1> 	cmp	ebx, M1L
  6225 00002810 7308                <1> 	jnb	short BAD_COMMAND
  6226                              <1>         ;xchg	bx, si
  6227 00002812 87DE                <1>         xchg	ebx, esi
  6228                              <1> 	;;;POP	AX			; RESTORE AX
  6229                              <1> 	;;;POP	BX			; AND DATA ADDRESS
  6230                              <1> 	
  6231                              <1> 	;;PUSH	CX
  6232                              <1> 	;;PUSH	AX			; ADJUST ES:BX
  6233                              <1> 	;MOV	CX,BX			; GET 3 HIGH ORDER NIBBLES OF BX
  6234                              <1> 	;SHR	CX,4
  6235                              <1> 	;MOV	AX,ES
  6236                              <1> 	;ADD	AX,CX
  6237                              <1> 	;MOV	ES,AX
  6238                              <1> 	;AND	BX,000FH		; ES:BX CHANGED TO ES:000X
  6239                              <1> 	;;POP	AX
  6240                              <1> 	;;POP	CX
  6241                              <1> 	;;JMP	word [CS:SI+M1]
  6242                              <1> 	;jmp	word [SI+M1]
  6243 00002814 FFA6[6B260000]      <1> 	jmp	dword [esi+M1]
  6244                              <1> ;;BAD_COMMAND_POP:
  6245                              <1> ;;	POP	AX
  6246                              <1> ;;	POP	BX
  6247                              <1> BAD_COMMAND:
  6248 0000281A C605[6F6B0000]01    <1>         MOV     byte [DISK_STATUS1],BAD_CMD  ; COMMAND ERROR
  6249 00002821 B000                <1> 	MOV	AL,0
  6250 00002823 C3                  <1> 	RETn
  6251                              <1> 
  6252                              <1> ;----------------------------------------
  6253                              <1> ;	RESET THE DISK SYSTEM  (AH=00H) :
  6254                              <1> ;----------------------------------------
  6255                              <1> 
  6256                              <1> ; 18-1-2015 : one controller reset (not other one)
  6257                              <1> 
  6258                              <1> DISK_RESET:
  6259 00002824 FA                  <1> 	CLI
  6260 00002825 E4A1                <1> 	IN	AL,INTB01		; GET THE MASK REGISTER
  6261                              <1> 	;JMP	$+2
  6262                              <1> 	IODELAY
  2149 00002827 EB00                <2>  jmp short $+2
  2150 00002829 EB00                <2>  jmp short $+2
  6263                              <1> 	;AND	AL,0BFH 		; ENABLE FIXED DISK INTERRUPT
  6264 0000282B 243F                <1> 	and	al,3Fh			; 22/12/2014 (IRQ 14 & IRQ 15)
  6265 0000282D E6A1                <1> 	OUT	INTB01,AL
  6266 0000282F FB                  <1> 	STI				; START INTERRUPTS
  6267                              <1> 	; 14/02/2015
  6268                              <1> 	;mov	di, dx
  6269                              <1> 	; 24/12/2021
  6270 00002830 89D7                <1> 	mov	edi, edx	
  6271                              <1> 	; 04/01/2015
  6272                              <1> 	;xor	di,di
  6273                              <1> drst0:
  6274 00002832 B004                <1> 	MOV	AL,04H  ; bit 2 - SRST 
  6275                              <1> 	;MOV	DX,HF_REG_PORT
  6276 00002834 668B15[C6650000]    <1> 	MOV	DX,[HF_REG_PORT]
  6277 0000283B EE                  <1> 	OUT	DX,AL			; RESET
  6278                              <1> ;	MOV	CX,10			; DELAY COUNT
  6279                              <1> ;DRD:	DEC	CX
  6280                              <1> ;	JNZ	short DRD		; WAIT 4.8 MICRO-SEC
  6281                              <1> 	;mov	cx,2			; wait for 30 micro seconds	
  6282 0000283C B902000000          <1>         mov	ecx, 2 ; 21/02/2015
  6283 00002841 E877ECFFFF          <1> 	call    WAITF                   ; (Award Bios 1999 - WAIT_REFRESH,
  6284                              <1>                                         ; 40 micro seconds)
  6285 00002846 A0[716B0000]        <1> 	mov	al,[CONTROL_BYTE]
  6286 0000284B 240F                <1> 	AND	AL,0FH			; SET HEAD OPTION
  6287 0000284D EE                  <1> 	OUT	DX,AL			; TURN RESET OFF
  6288 0000284E E807040000          <1> 	CALL	NOT_BUSY
  6289 00002853 7515                <1> 	JNZ	short DRERR		; TIME OUT ON RESET
  6290 00002855 668B15[C4650000]    <1> 	MOV	DX,[HF_PORT]
  6291 0000285C FEC2                <1> 	inc	dl  ; HF_PORT+1
  6292                              <1> 	; 02/01/2015 - Award BIOS 1999 - AHDSK.ASM
  6293                              <1>         ;mov	cl, 10
  6294 0000285E B90A000000          <1>         mov     ecx, 10 ; 21/02/2015 
  6295                              <1> drst1:
  6296 00002863 EC                  <1> 	IN	AL,DX			; GET RESET STATUS
  6297 00002864 3C01                <1> 	CMP	AL,1
  6298                              <1> 	; 04/01/2015
  6299 00002866 740A                <1> 	jz	short drst2
  6300                              <1> 	;JNZ	short DRERR		; BAD RESET STATUS
  6301                              <1>         	; Drive/Head Register - bit 4
  6302 00002868 E2F9                <1> 	loop	drst1
  6303                              <1> DRERR:	
  6304 0000286A C605[6F6B0000]05    <1> 	MOV	byte [DISK_STATUS1],BAD_RESET ; CARD FAILED
  6305 00002871 C3                  <1> 	RETn
  6306                              <1> drst2:
  6307                              <1> 	; 14/02/2015
  6308                              <1> 	;mov	dx, di
  6309                              <1> 	; 24/12/2021
  6310 00002872 89FA                <1> 	mov	edx, edi
  6311                              <1> ;drst3:
  6312                              <1> ;	; 05/01/2015
  6313                              <1> ;	shl 	di,1
  6314                              <1> ;	; 04/01/2015
  6315                              <1> ;	mov	ax,[di+hd_cports]
  6316                              <1> ;	cmp	ax,[HF_REG_PORT]
  6317                              <1> ;	je	short drst4
  6318                              <1> ;	mov	[HF_REG_PORT], ax
  6319                              <1> ;	; 03/01/2015
  6320                              <1> ;	mov	ax,[di+hd_ports]
  6321                              <1> ;       mov     [HF_PORT], ax
  6322                              <1> ;	; 05/01/2014
  6323                              <1> ;	shr	di,1
  6324                              <1> ;	; 04/01/2015
  6325                              <1> ;	jmp	short drst0	; reset other controller
  6326                              <1> ;drst4:
  6327                              <1> ;	; 05/01/2015
  6328                              <1> ;	shr	di,1
  6329                              <1> ;	mov	al,[di+hd_dregs]
  6330                              <1> ;	and	al,10h ; bit 4 only
  6331                              <1> ;	shr	al,4 ; bit 4  -> bit 0
  6332                              <1> ;	mov	[hf_m_s], al ; (0 = master, 1 = slave)
  6333                              <1> 	;
  6334 00002874 A0[C8650000]        <1> 	mov	al, [hf_m_s] ; 18/01/2015
  6335 00002879 A801                <1> 	test	al,1
  6336                              <1> ;	jnz	short drst6
  6337 0000287B 7516                <1>         jnz     short drst4
  6338 0000287D 8065FDEF            <1> 	AND     byte [CMD_BLOCK+5],0EFH ; SET TO DRIVE 0
  6339                              <1> ;drst5:
  6340                              <1> drst3:
  6341 00002881 E80B010000          <1> 	CALL	INIT_DRV		; SET MAX HEADS
  6342                              <1> 	;mov	dx,di
  6343 00002886 E8C3010000          <1> 	CALL	HDISK_RECAL		; RECAL TO RESET SEEK SPEED
  6344                              <1> 	; 04/01/2014
  6345                              <1> ;	inc	di
  6346                              <1> ;	mov	dx,di
  6347                              <1> ;	cmp	dl,[HF_NUM]
  6348                              <1> ;	jb	short drst3
  6349                              <1> ;DRE:
  6350 0000288B C605[6F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; IGNORE ANY SET UP ERRORS
  6351 00002892 C3                  <1> 	RETn
  6352                              <1> ;drst6:
  6353                              <1> drst4:		; Drive/Head Register - bit 4
  6354 00002893 804DFD10            <1> 	OR      byte [CMD_BLOCK+5],010H ; SET TO DRIVE 1     
  6355                              <1>         ;jmp    short drst5
  6356 00002897 EBE8                <1>         jmp     short drst3
  6357                              <1> 
  6358                              <1> ;----------------------------------------
  6359                              <1> ;	DISK STATUS ROUTINE  (AH = 01H) :
  6360                              <1> ;----------------------------------------
  6361                              <1> 
  6362                              <1> RETURN_STATUS:
  6363 00002899 A0[6F6B0000]        <1> 	MOV	AL,[DISK_STATUS1]	; OBTAIN PREVIOUS STATUS
  6364 0000289E C605[6F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0   ; RESET STATUS
  6365 000028A5 C3                  <1> 	RETn
  6366                              <1> 
  6367                              <1> ;----------------------------------------
  6368                              <1> ;	DISK READ ROUTINE    (AH = 02H) :
  6369                              <1> ;----------------------------------------
  6370                              <1> 
  6371                              <1> DISK_READ:
  6372 000028A6 C645FE20            <1> 	MOV	byte [CMD_BLOCK+6],READ_CMD
  6373 000028AA E92A020000          <1>         JMP     COMMANDI
  6374                              <1> 
  6375                              <1> ;----------------------------------------
  6376                              <1> ;	DISK WRITE ROUTINE   (AH = 03H) :
  6377                              <1> ;----------------------------------------
  6378                              <1> 
  6379                              <1> DISK_WRITE:
  6380 000028AF C645FE30            <1> 	MOV	byte [CMD_BLOCK+6],WRITE_CMD
  6381 000028B3 E976020000          <1>         JMP     COMMANDO
  6382                              <1> 
  6383                              <1> ;----------------------------------------
  6384                              <1> ;	DISK VERIFY	     (AH = 04H) :
  6385                              <1> ;----------------------------------------
  6386                              <1> 
  6387                              <1> DISK_VERF:
  6388 000028B8 C645FE40            <1> 	MOV	byte [CMD_BLOCK+6],VERIFY_CMD
  6389 000028BC E8E4020000          <1> 	CALL	COMMAND
  6390 000028C1 750C                <1> 	JNZ	short VERF_EXIT		; CONTROLLER STILL BUSY
  6391 000028C3 E856030000          <1> 	CALL	_WAIT			; (Original: CALL WAIT)	
  6392 000028C8 7505                <1> 	JNZ	short VERF_EXIT		; TIME OUT
  6393 000028CA E8E3030000          <1> 	CALL	CHECK_STATUS
  6394                              <1> VERF_EXIT:
  6395 000028CF C3                  <1> 	RETn
  6396                              <1> 
  6397                              <1> ;----------------------------------------
  6398                              <1> ;	FORMATTING	     (AH = 05H) :
  6399                              <1> ;----------------------------------------
  6400                              <1> 
  6401                              <1> FMT_TRK:				; FORMAT TRACK	(AH = 005H)
  6402 000028D0 C645FE50            <1> 	MOV	byte [CMD_BLOCK+6],FMTTRK_CMD
  6403                              <1> 	;PUSH	ES
  6404                              <1> 	;PUSH	BX
  6405 000028D4 53                  <1> 	push	ebx
  6406 000028D5 E885040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETERS ADDRESS
  6407                              <1> 	;MOV	AL,[ES:BX+14]		; GET SECTORS/TRACK
  6408 000028DA 8A430E              <1> 	mov	al, [ebx+14]
  6409 000028DD 8845F9              <1> 	MOV	[CMD_BLOCK+1],AL 	; SET SECTOR COUNT IN COMMAND
  6410 000028E0 5B                  <1> 	pop	ebx
  6411                              <1> 	;POP	BX
  6412                              <1> 	;POP	ES
  6413 000028E1 E94F020000          <1>         JMP     CMD_OF                  ; GO EXECUTE THE COMMAND
  6414                              <1> 
  6415                              <1> ;----------------------------------------
  6416                              <1> ;	READ DASD TYPE	     (AH = 15H) :
  6417                              <1> ;----------------------------------------
  6418                              <1> 
  6419                              <1> READ_DASD_TYPE:
  6420                              <1> READ_D_T:				; GET DRIVE PARAMETERS
  6421 000028E6 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6422                              <1> 	;PUSH	ES
  6423 000028E7 53                  <1> 	PUSH	eBX
  6424                              <1> 	;CALL	DDS			; ESTABLISH ADDRESSING
  6425                              <1> 	;push	cs
  6426                              <1> 	;pop	ds
  6427 000028E8 66BB1000            <1>         mov	bx, KDATA
  6428 000028EC 8EDB                <1> 	mov	ds, bx
  6429                              <1> 	;mov	es, bx
  6430 000028EE C605[6F6B0000]00    <1> 	MOV     byte [DISK_STATUS1],0
  6431 000028F5 8A1D[706B0000]      <1> 	MOV	BL,[HF_NUM]		; GET NUMBER OF DRIVES
  6432 000028FB 80E27F              <1> 	AND	DL,7FH			; GET DRIVE NUMBER
  6433 000028FE 38D3                <1> 	CMP	BL,DL
  6434 00002900 7625                <1> 	JBE	short RDT_NOT_PRESENT 	; RETURN DRIVE NOT PRESENT
  6435 00002902 E858040000          <1> 	CALL	GET_VEC 		; GET DISK PARAMETER ADDRESS
  6436                              <1> 	;MOV	AL,[ES:BX+2]		; HEADS
  6437 00002907 8A4302              <1> 	mov	al, [ebx+2]
  6438                              <1> 	;MOV	CL,[ES:BX+14]
  6439 0000290A 8A4B0E              <1> 	mov	cl, [ebx+14]
  6440 0000290D F6E9                <1> 	IMUL	CL			; * NUMBER OF SECTORS
  6441                              <1> 	;MOV	CX,[ES:BX]		; MAX NUMBER OF CYLINDERS
  6442 0000290F 668B0B              <1> 	mov	cx, [ebx]
  6443                              <1> 	;
  6444                              <1> 	; 02/01/2015 
  6445                              <1> 	; ** leave the last cylinder as reserved for diagnostics **
  6446                              <1> 	; (Also in Award BIOS - 1999, AHDSK.ASM, FUN15 -> sub ax, 1)
  6447 00002912 6649                <1> 	DEC	CX			; LEAVE ONE FOR DIAGNOSTICS
  6448                              <1> 	;
  6449 00002914 66F7E9              <1> 	IMUL	CX			; NUMBER OF SECTORS
  6450 00002917 6689D1              <1> 	MOV	CX,DX			; HIGH ORDER HALF
  6451 0000291A 6689C2              <1> 	MOV	DX,AX			; LOW ORDER HALF
  6452                              <1> 	;SUB	AX,AX
  6453 0000291D 28C0                <1> 	sub	al, al
  6454 0000291F B403                <1> 	MOV	AH,03H			; INDICATE FIXED DISK
  6455 00002921 5B                  <1> RDT2:	POP	eBX			; RESTORE REGISTERS
  6456                              <1> 	;POP	ES
  6457 00002922 1F                  <1> 	POP	DS
  6458 00002923 F8                  <1> 	CLC				; CLEAR CARRY
  6459                              <1> 	;RETf	2
  6460 00002924 CA0400              <1> 	retf	4
  6461                              <1> RDT_NOT_PRESENT:
  6462                              <1> 	;SUB	AX,AX			; DRIVE NOT PRESENT RETURN
  6463                              <1> 	; 24/12/2021
  6464 00002927 29C0                <1> 	sub	eax, eax
  6465                              <1> 	;MOV	CX,AX			; ZERO BLOCK COUNT
  6466                              <1> 	;MOV	DX,AX
  6467 00002929 89C1                <1> 	mov	ecx, eax
  6468 0000292B 89C2                <1> 	mov	edx, eax
  6469 0000292D EBF2                <1> 	JMP	short RDT2
  6470                              <1> 
  6471                              <1> ;----------------------------------------
  6472                              <1> ;	GET PARAMETERS	     (AH = 08H) :
  6473                              <1> ;----------------------------------------
  6474                              <1> 
  6475                              <1> GET_PARM_N:
  6476                              <1> ;GET_PARM:				; GET DRIVE PARAMETERS
  6477 0000292F 1E                  <1> 	PUSH	DS			; SAVE REGISTERS
  6478                              <1> 	;PUSH	ES
  6479 00002930 53                  <1> 	PUSH	eBX
  6480                              <1> 	;MOV	AX,ABS0 		; ESTABLISH ADDRESSING
  6481                              <1> 	;MOV	DS,AX
  6482                              <1> 	;TEST	DL,1			; CHECK FOR DRIVE 1
  6483                              <1> 	;JZ	short G0
  6484                              <1> 	;LES	BX,@HF1_TBL_VEC
  6485                              <1> 	;JMP	SHORT G1
  6486                              <1> ;G0:	LES	BX,@HF_TBL_VEC
  6487                              <1> ;G1:
  6488                              <1> 	;CALL	DDS			; ESTABLISH SEGMENT
  6489                              <1> 	; 22/12/2014
  6490                              <1> 	;push	cs
  6491                              <1> 	;pop	ds
  6492 00002931 66BB1000            <1> 	mov	bx, KDATA
  6493 00002935 8EDB                <1> 	mov	ds, bx
  6494                              <1> 	;mov	es, bx
  6495                              <1> 	;
  6496 00002937 80EA80              <1> 	SUB	DL,80H
  6497 0000293A 80FA04              <1> 	CMP	DL,MAX_FILE		; TEST WITHIN RANGE
  6498 0000293D 7340                <1> 	JAE	short G4
  6499                              <1> 	;
  6500 0000293F 31DB                <1> 	xor	ebx, ebx ; 21/02/2015
  6501                              <1> 	; 22/12/2014
  6502 00002941 88D3                <1> 	mov	bl, dl
  6503                              <1> 	;xor	bh, bh  
  6504 00002943 C0E302              <1> 	shl	bl, 2			; convert index to offset
  6505                              <1> 	;add	bx, HF_TBL_VEC
  6506 00002946 81C3[746B0000]      <1> 	add	ebx, HF_TBL_VEC
  6507                              <1> 	;mov	ax, [bx+2]
  6508                              <1> 	;mov	es, ax			; dpt segment
  6509                              <1> 	;mov	bx, [bx]		; dpt offset
  6510 0000294C 8B1B                <1> 	mov	ebx, [ebx] ; 32 bit offset	
  6511                              <1> 
  6512 0000294E C605[6F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6513                              <1>         ;MOV     AX,[ES:BX]              ; MAX NUMBER OF CYLINDERS
  6514 00002955 668B03              <1> 	mov	ax, [ebx]
  6515                              <1> 	;;SUB	AX,2			; ADJUST FOR 0-N
  6516 00002958 6648                <1> 	dec	ax			; max. cylinder number
  6517 0000295A 88C5                <1> 	MOV	CH,AL
  6518 0000295C 66250003            <1> 	AND	AX,0300H		; HIGH TWO BITS OF CYLINDER
  6519 00002960 66D1E8              <1> 	SHR	AX,1
  6520 00002963 66D1E8              <1> 	SHR	AX,1
  6521                              <1> 	;OR	AL,[ES:BX+14]		; SECTORS
  6522 00002966 0A430E              <1> 	or	al, [ebx+14]
  6523 00002969 88C1                <1> 	MOV	CL,AL
  6524                              <1> 	;MOV	DH,[ES:BX+2]		; HEADS
  6525 0000296B 8A7302              <1> 	mov	dh, [ebx+2]
  6526 0000296E FECE                <1> 	DEC	DH			; 0-N RANGE
  6527 00002970 8A15[706B0000]      <1> 	MOV	DL,[HF_NUM]		; DRIVE COUNT
  6528                              <1> 	;SUB	AX,AX
  6529                              <1> 	; 24/12/2021
  6530 00002976 29C0                <1> 	sub	eax, eax
  6531                              <1> 	; 27/12/2014 
  6532                              <1> 	; ES:DI = Address of disk parameter table from BIOS
  6533                              <1> 	; (Programmer's Guide to the AMIBIOS - 1993)
  6534                              <1> 	;mov	di, bx			; HDPT offset
  6535 00002978 89DF                <1> 	mov	edi, ebx
  6536                              <1> G5:
  6537 0000297A 5B                  <1> 	POP	eBX			; RESTORE REGISTERS
  6538                              <1> 	;POP	ES
  6539 0000297B 1F                  <1> 	POP	DS
  6540                              <1> 	;RETf	2
  6541 0000297C CA0400              <1> 	retf	4
  6542                              <1> G4:
  6543 0000297F C605[6F6B0000]07    <1> 	MOV     byte [DISK_STATUS1],INIT_FAIL ; OPERATION FAILED
  6544                              <1> 	; 24/12/2021
  6545 00002986 29C0                <1> 	sub	eax, eax
  6546 00002988 B407                <1> 	MOV	AH,INIT_FAIL
  6547                              <1> 	;SUB	AL,AL
  6548                              <1> 	;SUB	DX,DX
  6549 0000298A 29D2                <1> 	sub	edx, edx
  6550                              <1> 	;SUB	CX,CX
  6551 0000298C 29C9                <1> 	sub	ecx, ecx
  6552 0000298E F9                  <1> 	STC				; SET ERROR FLAG
  6553 0000298F EBE9                <1> 	JMP	short G5
  6554                              <1> 
  6555                              <1> ;----------------------------------------
  6556                              <1> ;	INITIALIZE DRIVE     (AH = 09H) :
  6557                              <1> ;----------------------------------------
  6558                              <1> 	; 03/01/2015
  6559                              <1> 	; According to ATA-ATAPI specification v2.0 to v5.0
  6560                              <1> 	; logical sector per logical track
  6561                              <1> 	; and logical heads - 1 would be set but
  6562                              <1> 	; it is seen as it will be good
  6563                              <1> 	; if physical parameters will be set here
  6564                              <1> 	; because, number of heads <= 16.
  6565                              <1> 	; (logical heads usually more than 16)
  6566                              <1> 	; NOTE: ATA logical parameters (software C, H, S)
  6567                              <1> 	;	== INT 13h physical parameters
  6568                              <1> 
  6569                              <1> ;INIT_DRV:
  6570                              <1> ;	MOV	byte [CMD_BLOCK+6],SET_PARM_CMD
  6571                              <1> ;	CALL	GET_VEC 		; ES:BX -> PARAMETER BLOCK
  6572                              <1> ;	MOV	AL,[ES:BX+2]		; GET NUMBER OF HEADS
  6573                              <1> ;	DEC	AL			; CONVERT TO 0-INDEX
  6574                              <1> ;	MOV	AH,[CMD_BLOCK+5] 	; GET SDH REGISTER
  6575                              <1> ;	AND	AH,0F0H 		; CHANGE HEAD NUMBER
  6576                              <1> ;	OR	AH,AL			; TO MAX HEAD
  6577                              <1> ;	MOV	[CMD_BLOCK+5],AH
  6578                              <1> ;	MOV	AL,[ES:BX+14]		; MAX SECTOR NUMBER
  6579                              <1> ;	MOV	[CMD_BLOCK+1],AL
  6580                              <1> ;	SUB	AX,AX
  6581                              <1> ;	MOV	[CMD_BLOCK+3],AL 	; ZERO FLAGS
  6582                              <1> ;	CALL	COMMAND 		; TELL CONTROLLER
  6583                              <1> ;	JNZ	short INIT_EXIT		; CONTROLLER BUSY ERROR
  6584                              <1> ;	CALL	NOT_BUSY		; WAIT FOR IT TO BE DONE
  6585                              <1> ;	JNZ	short INIT_EXIT		; TIME OUT
  6586                              <1> ;	CALL	CHECK_STATUS
  6587                              <1> ;INIT_EXIT:
  6588                              <1> ;	RETn
  6589                              <1> 
  6590                              <1> ; 04/01/2015
  6591                              <1> ; 02/01/2015 - Derived from from AWARD BIOS 1999
  6592                              <1> ;				 AHDSK.ASM - INIT_DRIVE
  6593                              <1> INIT_DRV:
  6594                              <1> 	;xor	ah,ah
  6595 00002991 31C0                <1> 	xor	eax,eax ; 21/02/2015
  6596 00002993 B00B                <1> 	mov	al,11 ; Physical heads from translated HDPT
  6597 00002995 3825[846B0000]      <1>         cmp     [LBAMode], ah   ; 0
  6598 0000299B 7702                <1> 	ja	short idrv0
  6599 0000299D B002                <1> 	mov	al,2  ; Physical heads from standard HDPT
  6600                              <1> idrv0:
  6601                              <1> 	; DL = drive number (0 based)
  6602 0000299F E8BB030000          <1> 	call	GET_VEC
  6603                              <1> 	;push	bx
  6604 000029A4 53                  <1> 	push	ebx ; 21/02/2015
  6605                              <1> 	;add	bx,ax
  6606 000029A5 01C3                <1> 	add	ebx,eax
  6607                              <1> 	;; 05/01/2015
  6608 000029A7 8A25[C8650000]      <1> 	mov	ah,[hf_m_s] ; drive number (0= master, 1= slave)
  6609                              <1> 	;;and 	ah,1 
  6610 000029AD C0E404              <1> 	shl	ah,4
  6611 000029B0 80CCA0              <1> 	or	ah,0A0h  ; Drive/Head register - 10100000b (A0h)	
  6612                              <1> 	;mov	al,[es:bx]
  6613 000029B3 8A03                <1> 	mov	al,[ebx] ; 21/02/2015
  6614 000029B5 FEC8                <1> 	dec	al	 ; last head number 
  6615                              <1> 	;and	al,0Fh
  6616 000029B7 08E0                <1> 	or	al,ah	 ; lower 4 bits for head number
  6617                              <1> 	;
  6618 000029B9 C645FE91            <1> 	mov	byte [CMD_BLOCK+6],SET_PARM_CMD
  6619 000029BD 8845FD              <1> 	mov	[CMD_BLOCK+5],al
  6620                              <1> 	;pop	bx
  6621 000029C0 5B                  <1> 	pop	ebx
  6622 000029C1 29C0                <1> 	sub	eax,eax ; 21/02/2015
  6623 000029C3 B004                <1> 	mov	al,4 ; Physical sec per track from translated HDPT
  6624 000029C5 803D[846B0000]00    <1> 	cmp	byte [LBAMode],0
  6625 000029CC 7702                <1> 	ja	short idrv1
  6626 000029CE B00E                <1> 	mov	al,14 ; Physical sec per track from standard HDPT
  6627                              <1> idrv1:
  6628                              <1> 	;xor	ah,ah
  6629                              <1> 	;add	bx,ax
  6630 000029D0 01C3                <1> 	add	ebx,eax ; 21/02/2015
  6631                              <1> 	;mov	al,[es:bx]
  6632                              <1> 			; sector number
  6633 000029D2 8A03                <1> 	mov	al,[ebx]
  6634 000029D4 8845F9              <1> 	mov	[CMD_BLOCK+1],al
  6635 000029D7 28C0                <1> 	sub	al,al
  6636 000029D9 8845FB              <1> 	mov	[CMD_BLOCK+3],al  ; ZERO FLAGS
  6637 000029DC E8C4010000          <1> 	call	COMMAND 	  ; TELL CONTROLLER
  6638 000029E1 750C                <1> 	jnz	short INIT_EXIT	  ; CONTROLLER BUSY ERROR
  6639 000029E3 E872020000          <1> 	call	NOT_BUSY	  ; WAIT FOR IT TO BE DONE
  6640 000029E8 7505                <1> 	jnz	short INIT_EXIT	  ; TIME OUT
  6641 000029EA E8C3020000          <1> 	call	CHECK_STATUS
  6642                              <1> INIT_EXIT:
  6643 000029EF C3                  <1> 	RETn
  6644                              <1> 
  6645                              <1> ;----------------------------------------
  6646                              <1> ;	READ LONG	     (AH = 0AH) :
  6647                              <1> ;----------------------------------------
  6648                              <1> 
  6649                              <1> RD_LONG:
  6650                              <1> 	;MOV	@CMD_BLOCK+6,READ_CMD OR ECC_MODE
  6651 000029F0 C645FE22            <1>         mov     byte [CMD_BLOCK+6],READ_CMD + ECC_MODE 
  6652 000029F4 E9E0000000          <1>         JMP     COMMANDI
  6653                              <1> 
  6654                              <1> ;----------------------------------------
  6655                              <1> ;	WRITE LONG	     (AH = 0BH) :
  6656                              <1> ;----------------------------------------
  6657                              <1> 
  6658                              <1> WR_LONG:
  6659                              <1> 	;MOV	@CMD_BLOCK+6,WRITE_CMD OR ECC_MODE
  6660 000029F9 C645FE32            <1>         MOV     byte [CMD_BLOCK+6],WRITE_CMD + ECC_MODE
  6661 000029FD E92C010000          <1>         JMP     COMMANDO
  6662                              <1> 
  6663                              <1> ;----------------------------------------
  6664                              <1> ;	SEEK		     (AH = 0CH) :
  6665                              <1> ;----------------------------------------
  6666                              <1> 
  6667                              <1> DISK_SEEK:
  6668 00002A02 C645FE70            <1>         MOV     byte [CMD_BLOCK+6],SEEK_CMD
  6669 00002A06 E89A010000          <1> 	CALL	COMMAND
  6670 00002A0B 751C                <1> 	JNZ	short DS_EXIT 		; CONTROLLER BUSY ERROR
  6671 00002A0D E80C020000          <1> 	CALL	_WAIT
  6672 00002A12 7515                <1>         JNZ     DS_EXIT                 ; TIME OUT ON SEEK
  6673 00002A14 E899020000          <1> 	CALL	CHECK_STATUS
  6674 00002A19 803D[6F6B0000]40    <1>         CMP     byte [DISK_STATUS1],BAD_SEEK
  6675 00002A20 7507                <1> 	JNE	short DS_EXIT
  6676 00002A22 C605[6F6B0000]00    <1>         MOV     byte [DISK_STATUS1],0
  6677                              <1> DS_EXIT:
  6678 00002A29 C3                  <1> 	RETn
  6679                              <1> 
  6680                              <1> ;----------------------------------------
  6681                              <1> ;	TEST DISK READY      (AH = 10H) :
  6682                              <1> ;----------------------------------------
  6683                              <1> 
  6684                              <1> TST_RDY:				; WAIT FOR CONTROLLER
  6685 00002A2A E82B020000          <1> 	CALL	NOT_BUSY
  6686 00002A2F 751C                <1> 	JNZ	short TR_EX
  6687 00002A31 8A45FD              <1> 	MOV	AL,[CMD_BLOCK+5] 	; SELECT DRIVE
  6688 00002A34 668B15[C4650000]    <1> 	MOV	DX,[HF_PORT]
  6689 00002A3B 80C206              <1> 	add	dl,6
  6690 00002A3E EE                  <1> 	OUT	DX,AL
  6691 00002A3F E886020000          <1> 	CALL	CHECK_ST		; CHECK STATUS ONLY
  6692 00002A44 7507                <1> 	JNZ	short TR_EX
  6693 00002A46 C605[6F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0 	; WIPE OUT DATA CORRECTED ERROR
  6694                              <1> TR_EX:	
  6695 00002A4D C3                  <1> 	RETn
  6696                              <1> 
  6697                              <1> ;----------------------------------------
  6698                              <1> ;	RECALIBRATE	     (AH = 11H) :
  6699                              <1> ;----------------------------------------
  6700                              <1> 
  6701                              <1> HDISK_RECAL:
  6702 00002A4E C645FE10            <1>         MOV     byte [CMD_BLOCK+6],RECAL_CMD ; 10h, 16
  6703 00002A52 E84E010000          <1> 	CALL	COMMAND 		; START THE OPERATION
  6704 00002A57 7523                <1> 	JNZ	short RECAL_EXIT	; ERROR
  6705 00002A59 E8C0010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION
  6706 00002A5E 7407                <1> 	JZ	short RECAL_X 		; TIME OUT ONE OK ?
  6707 00002A60 E8B9010000          <1> 	CALL	_WAIT			; WAIT FOR COMPLETION LONGER
  6708 00002A65 7515                <1> 	JNZ	short RECAL_EXIT	; TIME OUT TWO TIMES IS ERROR
  6709                              <1> RECAL_X:
  6710 00002A67 E846020000          <1> 	CALL	CHECK_STATUS
  6711 00002A6C 803D[6F6B0000]40    <1> 	CMP	byte [DISK_STATUS1],BAD_SEEK ; SEEK NOT COMPLETE
  6712 00002A73 7507                <1> 	JNE	short RECAL_EXIT	; IS OK
  6713 00002A75 C605[6F6B0000]00    <1> 	MOV	byte [DISK_STATUS1],0
  6714                              <1> RECAL_EXIT:
  6715 00002A7C 803D[6F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0
  6716 00002A83 C3                  <1> 	RETn
  6717                              <1> 
  6718                              <1> ;----------------------------------------
  6719                              <1> ;      CONTROLLER DIAGNOSTIC (AH = 14H) :
  6720                              <1> ;----------------------------------------
  6721                              <1> 
  6722                              <1> CTLR_DIAGNOSTIC:
  6723 00002A84 FA                  <1>         CLI                             ; DISABLE INTERRUPTS WHILE CHANGING MASK
  6724 00002A85 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6725                              <1> 	;AND	AL,0BFH
  6726 00002A87 243F                <1> 	and	al, 3Fh			; enable IRQ 14 & IRQ 15
  6727                              <1> 	;JMP	$+2
  6728                              <1> 	IODELAY
  2149 00002A89 EB00                <2>  jmp short $+2
  2150 00002A8B EB00                <2>  jmp short $+2
  6729 00002A8D E6A1                <1> 	OUT	INTB01,AL
  6730                              <1> 	IODELAY
  2149 00002A8F EB00                <2>  jmp short $+2
  2150 00002A91 EB00                <2>  jmp short $+2
  6731 00002A93 E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6732 00002A95 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6733                              <1> 	;JMP	$+2
  6734                              <1> 	IODELAY
  2149 00002A97 EB00                <2>  jmp short $+2
  2150 00002A99 EB00                <2>  jmp short $+2
  6735 00002A9B E621                <1> 	OUT	INTA01,AL
  6736 00002A9D FB                  <1> 	STI
  6737 00002A9E E8B7010000          <1> 	CALL	NOT_BUSY		; WAIT FOR CARD
  6738 00002AA3 752B                <1> 	JNZ	short CD_ERR		; BAD CARD
  6739                              <1> 	;MOV	DX, HF_PORT+7
  6740 00002AA5 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6741 00002AAC 80C207              <1> 	add	dl, 7
  6742 00002AAF B090                <1> 	MOV	AL,DIAG_CMD		; START DIAGNOSE
  6743 00002AB1 EE                  <1> 	OUT	DX,AL
  6744 00002AB2 E8A3010000          <1> 	CALL	NOT_BUSY		; WAIT FOR IT TO COMPLETE
  6745 00002AB7 B480                <1> 	MOV	AH,TIME_OUT
  6746 00002AB9 7517                <1> 	JNZ	short CD_EXIT 		; TIME OUT ON DIAGNOSTIC
  6747                              <1> 	;MOV	DX,HF_PORT+1		; GET ERROR REGISTER
  6748 00002ABB 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6749 00002AC2 FEC2                <1> 	inc	dl
  6750 00002AC4 EC                  <1> 	IN	AL,DX
  6751 00002AC5 A2[666B0000]        <1> 	MOV	[HF_ERROR],AL		; SAVE IT
  6752 00002ACA B400                <1> 	MOV	AH,0
  6753 00002ACC 3C01                <1> 	CMP	AL,1			; CHECK FOR ALL OK
  6754 00002ACE 7402                <1> 	JE	SHORT CD_EXIT
  6755 00002AD0 B420                <1> CD_ERR: MOV	AH,BAD_CNTLR
  6756                              <1> CD_EXIT:
  6757 00002AD2 8825[6F6B0000]      <1> 	MOV	[DISK_STATUS1],AH
  6758 00002AD8 C3                  <1> 	RETn
  6759                              <1> 
  6760                              <1> ;----------------------------------------
  6761                              <1> ; COMMANDI				:
  6762                              <1> ;	REPEATEDLY INPUTS DATA TILL	:
  6763                              <1> ;	NSECTOR RETURNS ZERO		:
  6764                              <1> ;----------------------------------------
  6765                              <1> COMMANDI:
  6766 00002AD9 E85A020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6767 00002ADE 724D                <1> 	JC	short CMD_ABORT
  6768                              <1> 	;MOV	DI,BX
  6769 00002AE0 89DF                <1> 	mov	edi, ebx ; 21/02/2015
  6770 00002AE2 E8BE000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6771 00002AE7 7544                <1> 	JNZ	short CMD_ABORT
  6772                              <1> CMD_I1:
  6773 00002AE9 E830010000          <1> 	CALL	_WAIT			; WAIT FOR DATA REQUEST INTERRUPT
  6774 00002AEE 753D                <1> 	JNZ	short TM_OUT		; TIME OUT
  6775                              <1> 	;MOV	CX,256			; SECTOR SIZE IN WORDS
  6776 00002AF0 B900010000          <1> 	mov	ecx, 256 ; 21/02/2015	
  6777                              <1> 	;MOV	DX,HF_PORT
  6778 00002AF5 668B15[C4650000]    <1> 	mov	dx,[HF_PORT]
  6779 00002AFC FA                  <1> 	CLI
  6780 00002AFD FC                  <1> 	CLD
  6781 00002AFE F3666D              <1> 	REP	INSW			; GET THE SECTOR
  6782 00002B01 FB                  <1> 	STI
  6783 00002B02 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL INPUT
  6784 00002B06 7419                <1> 	JZ	CMD_I3
  6785 00002B08 E87A010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6786 00002B0D 721E                <1> 	JC	short TM_OUT
  6787                              <1> 	;MOV	DX,HF_PORT
  6788 00002B0F 668B15[C4650000]    <1> 	mov	dx,[HF_PORT]
  6789                              <1> 	;MOV	CX,4			; GET ECC BYTES
  6790 00002B16 B904000000          <1> 	mov 	ecx, 4 ; mov cx, 4 
  6791 00002B1B EC                  <1> CMD_I2: IN	AL,DX
  6792                              <1> 	;MOV	[ES:DI],AL		; GO SLOW FOR BOARD
  6793 00002B1C 8807                <1> 	mov 	[edi], al ; 21/02/2015
  6794 00002B1E 47                  <1> 	INC	eDI
  6795 00002B1F E2FA                <1> 	LOOP	CMD_I2
  6796 00002B21 E88C010000          <1> CMD_I3: CALL	CHECK_STATUS
  6797 00002B26 7505                <1> 	JNZ	short CMD_ABORT		; ERROR RETURNED
  6798 00002B28 FE4DF9              <1> 	DEC	byte [CMD_BLOCK+1]	; CHECK FOR MORE
  6799 00002B2B 75BC                <1> 	JNZ	SHORT CMD_I1
  6800                              <1> CMD_ABORT:
  6801 00002B2D C3                  <1> TM_OUT: RETn
  6802                              <1> 
  6803                              <1> ;----------------------------------------
  6804                              <1> ; COMMANDO				:
  6805                              <1> ;	REPEATEDLY OUTPUTS DATA TILL	:
  6806                              <1> ;	NSECTOR RETURNS ZERO		:
  6807                              <1> ;----------------------------------------
  6808                              <1> COMMANDO:
  6809 00002B2E E805020000          <1> 	CALL	CHECK_DMA		; CHECK 64K BOUNDARY ERROR
  6810 00002B33 72F8                <1> 	JC	short CMD_ABORT
  6811 00002B35 89DE                <1> CMD_OF: MOV	eSI,eBX ; 21/02/2015
  6812 00002B37 E869000000          <1> 	CALL	COMMAND 		; OUTPUT COMMAND
  6813 00002B3C 75EF                <1> 	JNZ	short CMD_ABORT
  6814 00002B3E E844010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6815 00002B43 72E8                <1> 	JC	short TM_OUT			; TOO LONG
  6816                              <1> CMD_O1: ;PUSH	DS
  6817                              <1> 	;PUSH	ES			; MOVE ES TO DS
  6818                              <1> 	;POP	DS
  6819                              <1> 	;MOV	CX,256			; PUT THE DATA OUT TO THE CARD
  6820                              <1> 	;MOV	DX,HF_PORT
  6821                              <1> 	; 01/02/2015
  6822 00002B45 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6823                              <1> 	;push	es
  6824                              <1> 	;pop	ds
  6825                              <1> 	;mov	cx, 256
  6826 00002B4C B900010000          <1> 	mov	ecx, 256 ; 21/02/2015
  6827 00002B51 FA                  <1> 	CLI
  6828 00002B52 FC                  <1> 	CLD
  6829 00002B53 F3666F              <1> 	REP	OUTSW
  6830 00002B56 FB                  <1> 	STI
  6831                              <1> 	;POP	DS			; RESTORE DS
  6832 00002B57 F645FE02            <1> 	TEST	byte [CMD_BLOCK+6],ECC_MODE ; CHECK FOR NORMAL OUTPUT
  6833 00002B5B 7419                <1> 	JZ	short CMD_O3
  6834 00002B5D E825010000          <1> 	CALL	WAIT_DRQ		; WAIT FOR DATA REQUEST
  6835 00002B62 72C9                <1> 	JC	short TM_OUT
  6836                              <1> 	;MOV	DX,HF_PORT
  6837 00002B64 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6838                              <1> 	;MOV	CX,4			; OUTPUT THE ECC BYTES
  6839 00002B6B B904000000          <1> 	mov	ecx, 4  ; mov cx, 4
  6840                              <1> CMD_O2: ;MOV	AL,[ES:SI]
  6841 00002B70 8A06                <1> 	mov	al, [esi]
  6842 00002B72 EE                  <1> 	OUT	DX,AL
  6843 00002B73 46                  <1> 	INC	eSI
  6844 00002B74 E2FA                <1> 	LOOP	CMD_O2
  6845                              <1> CMD_O3:
  6846 00002B76 E8A3000000          <1> 	CALL	_WAIT			; WAIT FOR SECTOR COMPLETE INTERRUPT
  6847 00002B7B 75B0                <1> 	JNZ	short TM_OUT		; ERROR RETURNED
  6848 00002B7D E830010000          <1> 	CALL	CHECK_STATUS
  6849 00002B82 75A9                <1> 	JNZ	short CMD_ABORT
  6850 00002B84 F605[656B0000]08    <1> 	TEST	byte [HF_STATUS],ST_DRQ	; CHECK FOR MORE
  6851 00002B8B 75B8                <1> 	JNZ	SHORT CMD_O1
  6852                              <1> 	;MOV	DX,HF_PORT+2		; CHECK RESIDUAL SECTOR COUNT
  6853 00002B8D 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6854                              <1> 	;add	dl, 2
  6855 00002B94 FEC2                <1> 	inc	dl
  6856 00002B96 FEC2                <1> 	inc	dl
  6857 00002B98 EC                  <1> 	IN	AL,DX			;
  6858 00002B99 A8FF                <1> 	TEST	AL,0FFH 		;
  6859 00002B9B 7407                <1> 	JZ	short CMD_O4			; COUNT = 0  OK
  6860 00002B9D C605[6F6B0000]BB    <1> 	MOV	byte [DISK_STATUS1],UNDEF_ERR 
  6861                              <1> 					; OPERATION ABORTED - PARTIAL TRANSFER
  6862                              <1> CMD_O4:
  6863 00002BA4 C3                  <1> 	RETn
  6864                              <1> 
  6865                              <1> ;--------------------------------------------------------
  6866                              <1> ; COMMAND						:
  6867                              <1> ;	THIS ROUTINE OUTPUTS THE COMMAND BLOCK		:
  6868                              <1> ; OUTPUT						:
  6869                              <1> ;	BL = STATUS					:
  6870                              <1> ;	BH = ERROR REGISTER				:
  6871                              <1> ;--------------------------------------------------------
  6872                              <1> 
  6873                              <1> COMMAND:
  6874 00002BA5 53                  <1> 	PUSH	eBX			; WAIT FOR SEEK COMPLETE AND READY
  6875                              <1> 	;;MOV	CX,DELAY_2		; SET INITIAL DELAY BEFORE TEST
  6876                              <1> COMMAND1:
  6877                              <1> 	;;PUSH	CX			; SAVE LOOP COUNT
  6878 00002BA6 E87FFEFFFF          <1> 	CALL	TST_RDY 		; CHECK DRIVE READY
  6879                              <1> 	;;POP	CX
  6880 00002BAB 7419                <1> 	JZ	short COMMAND2		; DRIVE IS READY
  6881 00002BAD 803D[6F6B0000]80    <1>         CMP     byte [DISK_STATUS1],TIME_OUT ; TST_RDY TIMED OUT--GIVE UP
  6882                              <1> 	;JZ	short CMD_TIMEOUT
  6883                              <1> 	;;LOOP	COMMAND1		; KEEP TRYING FOR A WHILE
  6884                              <1> 	;JMP	SHORT COMMAND4		; ITS NOT GOING TO GET READY
  6885 00002BB4 7507                <1> 	jne	short COMMAND4
  6886                              <1> CMD_TIMEOUT:
  6887 00002BB6 C605[6F6B0000]20    <1> 	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6888                              <1> COMMAND4:
  6889 00002BBD 5B                  <1> 	POP	eBX
  6890 00002BBE 803D[6F6B0000]00    <1>         CMP     byte [DISK_STATUS1],0   ; SET CONDITION CODE FOR CALLER
  6891 00002BC5 C3                  <1> 	RETn
  6892                              <1> COMMAND2:
  6893 00002BC6 5B                  <1> 	POP	eBX
  6894 00002BC7 57                  <1> 	PUSH	eDI
  6895 00002BC8 C605[676B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0	; RESET INTERRUPT FLAG
  6896 00002BCF FA                  <1> 	CLI				; INHIBIT INTERRUPTS WHILE CHANGING MASK
  6897 00002BD0 E4A1                <1> 	IN	AL,INTB01		; TURN ON SECOND INTERRUPT CHIP
  6898                              <1> 	;AND	AL,0BFH
  6899 00002BD2 243F                <1> 	and	al, 3Fh			; Enable IRQ 14 & 15
  6900                              <1> 	;JMP	$+2
  6901                              <1> 	IODELAY
  2149 00002BD4 EB00                <2>  jmp short $+2
  2150 00002BD6 EB00                <2>  jmp short $+2
  6902 00002BD8 E6A1                <1> 	OUT	INTB01,AL
  6903 00002BDA E421                <1> 	IN	AL,INTA01		; LET INTERRUPTS PASS THRU TO
  6904 00002BDC 24FB                <1> 	AND	AL,0FBH 		;  SECOND CHIP
  6905                              <1> 	;JMP	$+2
  6906                              <1> 	IODELAY
  2149 00002BDE EB00                <2>  jmp short $+2
  2150 00002BE0 EB00                <2>  jmp short $+2
  6907 00002BE2 E621                <1> 	OUT	INTA01,AL
  6908 00002BE4 FB                  <1> 	STI
  6909 00002BE5 31FF                <1> 	XOR	eDI,eDI			; INDEX THE COMMAND TABLE
  6910                              <1> 	;MOV	DX,HF_PORT+1		; DISK ADDRESS
  6911 00002BE7 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  6912 00002BEE FEC2                <1> 	inc	dl
  6913 00002BF0 F605[716B0000]C0    <1> 	TEST	byte [CONTROL_BYTE],0C0H ; CHECK FOR RETRY SUPPRESSION
  6914 00002BF7 7411                <1> 	JZ	short COMMAND3
  6915 00002BF9 8A45FE              <1> 	MOV	AL, [CMD_BLOCK+6] 	; YES-GET OPERATION CODE
  6916 00002BFC 24F0                <1> 	AND	AL,0F0H 		; GET RID OF MODIFIERS
  6917 00002BFE 3C20                <1> 	CMP	AL,20H			; 20H-40H IS READ, WRITE, VERIFY
  6918 00002C00 7208                <1> 	JB	short COMMAND3
  6919 00002C02 3C40                <1> 	CMP	AL,40H
  6920 00002C04 7704                <1> 	JA	short COMMAND3
  6921 00002C06 804DFE01            <1> 	OR	byte [CMD_BLOCK+6],NO_RETRIES 
  6922                              <1> 					; VALID OPERATION FOR RETRY SUPPRESS
  6923                              <1> COMMAND3:
  6924 00002C0A 8A443DF8            <1> 	MOV	AL,[CMD_BLOCK+eDI]	; GET THE COMMAND STRING BYTE
  6925 00002C0E EE                  <1> 	OUT	DX,AL			; GIVE IT TO CONTROLLER
  6926                              <1> 	IODELAY
  2149 00002C0F EB00                <2>  jmp short $+2
  2150 00002C11 EB00                <2>  jmp short $+2
  6927 00002C13 47                  <1> 	INC	eDI			; NEXT BYTE IN COMMAND BLOCK
  6928 00002C14 6642                <1> 	INC	DX			; NEXT DISK ADAPTER REGISTER
  6929 00002C16 6683FF07            <1> 	cmp	di, 7	; 1/1/2015	; ALL DONE?
  6930 00002C1A 75EE                <1> 	JNZ	short COMMAND3		; NO--GO DO NEXT ONE
  6931 00002C1C 5F                  <1> 	POP	eDI
  6932 00002C1D C3                  <1> 	RETn				; ZERO FLAG IS SET
  6933                              <1> 
  6934                              <1> ;CMD_TIMEOUT:
  6935                              <1> ;	MOV	byte [DISK_STATUS1],BAD_CNTLR
  6936                              <1> ;COMMAND4:
  6937                              <1> ;	POP	BX
  6938                              <1> ;	CMP	[DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6939                              <1> ;	RETn
  6940                              <1> 
  6941                              <1> ;----------------------------------------
  6942                              <1> ;	WAIT FOR INTERRUPT		:
  6943                              <1> ;----------------------------------------
  6944                              <1> ;WAIT:
  6945                              <1> _WAIT:
  6946 00002C1E FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6947                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  6948                              <1> 	;CLC
  6949                              <1> 	;MOV	AX,9000H		; DEVICE WAIT INTERRUPT
  6950                              <1> 	;INT	15H
  6951                              <1> 	;JC	WT2			; DEVICE TIMED OUT
  6952                              <1> 	;MOV	BL,DELAY_1		; SET DELAY COUNT
  6953                              <1> 
  6954                              <1> 	;mov	bl, WAIT_HDU_INT_HI
  6955                              <1> 	;; 21/02/2015
  6956                              <1> 	;;mov	bl, WAIT_HDU_INT_HI + 1
  6957                              <1> 	;;mov	cx, WAIT_HDU_INT_LO
  6958 00002C1F B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH
  6959                              <1> 					; (AWARD BIOS -> WAIT_FOR_MEM)
  6960                              <1> ;-----	WAIT LOOP
  6961                              <1> 
  6962                              <1> WT1:	
  6963                              <1> 	;TEST	byte [HF_INT_FLAG],80H	; TEST FOR INTERRUPT
  6964 00002C24 F605[676B0000]C0    <1> 	test 	byte [HF_INT_FLAG],0C0h
  6965                              <1> 	;LOOPZ	WT1
  6966 00002C2B 7517                <1> 	JNZ	short WT3		; INTERRUPT--LETS GO
  6967                              <1> 	;DEC	BL
  6968                              <1> 	;JNZ	short WT1		; KEEP TRYING FOR A WHILE
  6969                              <1> 
  6970                              <1> WT1_hi:
  6971 00002C2D E461                <1> 	in	al, SYS1 ; 61h (PORT_B)	; wait for lo to hi
  6972 00002C2F A810                <1> 	test	al, 10h			; transition on memory
  6973 00002C31 75FA                <1> 	jnz	short WT1_hi		; refresh.
  6974                              <1> WT1_lo:
  6975 00002C33 E461                <1> 	in	al, SYS1 		; 061h (PORT_B)	
  6976 00002C35 A810                <1> 	test	al, 10h			
  6977 00002C37 74FA                <1> 	jz	short WT1_lo
  6978 00002C39 E2E9                <1> 	loop	WT1
  6979                              <1> 	;;or	bl, bl
  6980                              <1> 	;;jz	short WT2	
  6981                              <1> 	;;dec	bl
  6982                              <1> 	;;jmp	short WT1
  6983                              <1> 	;dec	bl
  6984                              <1> 	;jnz	short WT1	
  6985                              <1> 
  6986 00002C3B C605[6F6B0000]80    <1> WT2:	MOV	byte [DISK_STATUS1],TIME_OUT ; REPORT TIME OUT ERROR
  6987 00002C42 EB0E                <1> 	JMP	SHORT WT4
  6988 00002C44 C605[6F6B0000]00    <1> WT3:	MOV	byte [DISK_STATUS1],0
  6989 00002C4B C605[676B0000]00    <1> 	MOV	byte [HF_INT_FLAG],0
  6990 00002C52 803D[6F6B0000]00    <1> WT4:	CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  6991 00002C59 C3                  <1> 	RETn
  6992                              <1> 
  6993                              <1> ;----------------------------------------
  6994                              <1> ;	WAIT FOR CONTROLLER NOT BUSY	:
  6995                              <1> ;----------------------------------------
  6996                              <1> NOT_BUSY:
  6997 00002C5A FB                  <1> 	STI				; MAKE SURE INTERRUPTS ARE ON
  6998                              <1> 	;PUSH	eBX
  6999                              <1> 	;SUB	CX,CX			; SET INITIAL DELAY BEFORE TEST
  7000 00002C5B 668B15[C4650000]    <1> 	mov	DX, [HF_PORT]
  7001 00002C62 80C207              <1> 	add	dl, 7			; Status port (HF_PORT+7)
  7002                              <1> 	;MOV	BL,DELAY_1
  7003                              <1> 					; wait for 10 seconds
  7004                              <1> 	;mov 	cx, WAIT_HDU_INT_LO	; 1615h
  7005                              <1> 	;;mov 	bl, WAIT_HDU_INT_HI	;   05h
  7006                              <1> 	;mov	bl, WAIT_HDU_INT_HI + 1
  7007 00002C65 B915160500          <1> 	mov	ecx, WAIT_HDU_INT_LH  ; 21/02/2015
  7008                              <1> 	;
  7009                              <1> ;;      mov     byte [wait_count], 0    ; Reset wait counter
  7010                              <1> NB1:	
  7011 00002C6A EC                  <1> 	IN	AL,DX			; CHECK STATUS
  7012                              <1> 	;TEST	AL,ST_BUSY
  7013 00002C6B 2480                <1> 	and	al, ST_BUSY
  7014                              <1> 	;LOOPNZ	NB1
  7015 00002C6D 7410                <1> 	JZ	short NB2		; NOT BUSY--LETS GO
  7016                              <1> 	;DEC	BL			
  7017                              <1> 	;JNZ	short NB1		; KEEP TRYING FOR A WHILE
  7018                              <1> 
  7019 00002C6F E461                <1> NB1_hi: IN	AL,SYS1			; wait for hi to lo
  7020 00002C71 A810                <1> 	TEST	AL,010H			; transition on memory
  7021 00002C73 75FA                <1> 	JNZ	SHORT NB1_hi		; refresh.
  7022 00002C75 E461                <1> NB1_lo: IN	AL,SYS1
  7023 00002C77 A810                <1> 	TEST	AL,010H
  7024 00002C79 74FA                <1> 	JZ	short NB1_lo
  7025 00002C7B E2ED                <1> 	LOOP	NB1
  7026                              <1> 	;dec	bl
  7027                              <1> 	;jnz	short NB1
  7028                              <1> 	;
  7029                              <1> ;;      cmp     byte [wait_count], 182  ; 10 seconds (182 timer ticks)
  7030                              <1> ;;	jb	short NB1
  7031                              <1> 	;
  7032                              <1> 	;MOV	[DISK_STATUS1],TIME_OUT	; REPORT TIME OUT ERROR
  7033                              <1> 	;JMP	SHORT NB3
  7034 00002C7D B080                <1> 	mov	al, TIME_OUT
  7035                              <1> NB2:	
  7036                              <1> 	;MOV	byte [DISK_STATUS1],0
  7037                              <1> ;NB3:	
  7038                              <1> 	;POP	eBX
  7039 00002C7F A2[6F6B0000]        <1> 	mov	[DISK_STATUS1], al	;;; will be set after return
  7040                              <1> 	;CMP	byte [DISK_STATUS1],0 	; SET CONDITION CODE FOR CALLER
  7041 00002C84 08C0                <1> 	or	al, al			; (zf = 0 --> timeout)
  7042 00002C86 C3                  <1> 	RETn
  7043                              <1> 
  7044                              <1> ;----------------------------------------
  7045                              <1> ;	WAIT FOR DATA REQUEST		:
  7046                              <1> ;----------------------------------------
  7047                              <1> WAIT_DRQ:
  7048                              <1> 	;MOV	CX,DELAY_3
  7049                              <1> 	;MOV	DX,HF_PORT+7
  7050 00002C87 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  7051 00002C8E 80C207              <1> 	add	dl, 7
  7052                              <1> 	;;MOV	bl, WAIT_HDU_DRQ_HI	; 0
  7053                              <1> 	;MOV	cx, WAIT_HDU_DRQ_LO	; 1000 (30 milli seconds)
  7054                              <1> 					; (but it is written as 2000
  7055                              <1> 					; micro seconds in ATORGS.ASM file
  7056                              <1> 					; of Award Bios - 1999, D1A0622)
  7057 00002C91 B9E8030000          <1> 	mov 	ecx, WAIT_HDU_DRQ_LH ; 21/02/2015 
  7058 00002C96 EC                  <1> WQ_1:	IN	AL,DX			; GET STATUS
  7059 00002C97 A808                <1> 	TEST	AL,ST_DRQ		; WAIT FOR DRQ
  7060 00002C99 7516                <1> 	JNZ	short WQ_OK
  7061                              <1> 	;LOOP	WQ_1			; KEEP TRYING FOR A SHORT WHILE
  7062                              <1> WQ_hi:	
  7063 00002C9B E461                <1> 	IN	AL,SYS1			; wait for hi to lo
  7064 00002C9D A810                <1> 	TEST	AL,010H			; transition on memory
  7065 00002C9F 75FA                <1> 	JNZ	SHORT WQ_hi		; refresh.
  7066 00002CA1 E461                <1> WQ_lo:  IN      AL,SYS1
  7067 00002CA3 A810                <1> 	TEST	AL,010H
  7068 00002CA5 74FA                <1> 	JZ	SHORT WQ_lo
  7069 00002CA7 E2ED                <1> 	LOOP	WQ_1
  7070                              <1> 
  7071 00002CA9 C605[6F6B0000]80    <1>         MOV     byte [DISK_STATUS1],TIME_OUT ; ERROR
  7072 00002CB0 F9                  <1> 	STC
  7073                              <1> WQ_OK:
  7074 00002CB1 C3                  <1> 	RETn
  7075                              <1> ;WQ_OK:	;CLC
  7076                              <1> ;	RETn
  7077                              <1> 
  7078                              <1> ;----------------------------------------
  7079                              <1> ;	CHECK FIXED DISK STATUS 	:
  7080                              <1> ;----------------------------------------
  7081                              <1> CHECK_STATUS:
  7082 00002CB2 E813000000          <1> 	CALL	CHECK_ST		; CHECK THE STATUS BYTE
  7083 00002CB7 7509                <1> 	JNZ	short CHECK_S1		; AN ERROR WAS FOUND
  7084 00002CB9 A801                <1> 	TEST	AL,ST_ERROR		; WERE THERE ANY OTHER ERRORS
  7085 00002CBB 7405                <1> 	JZ	short CHECK_S1		; NO ERROR REPORTED
  7086 00002CBD E847000000          <1> 	CALL	CHECK_ER		; ERROR REPORTED
  7087                              <1> CHECK_S1:
  7088 00002CC2 803D[6F6B0000]00    <1> 	CMP	byte [DISK_STATUS1],0 	; SET STATUS FOR CALLER
  7089 00002CC9 C3                  <1> 	RETn
  7090                              <1> 
  7091                              <1> ;----------------------------------------
  7092                              <1> ;	CHECK FIXED DISK STATUS BYTE	:
  7093                              <1> ;----------------------------------------
  7094                              <1> CHECK_ST:
  7095                              <1> 	;MOV	DX,HF_PORT+7		; GET THE STATUS
  7096 00002CCA 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]
  7097 00002CD1 80C207              <1> 	add	dl, 7
  7098 00002CD4 EC                  <1> 	IN	AL,DX
  7099 00002CD5 A2[656B0000]        <1> 	MOV	[HF_STATUS],AL
  7100 00002CDA B400                <1> 	MOV	AH,0
  7101 00002CDC A880                <1> 	TEST	AL,ST_BUSY		; IF STILL BUSY
  7102 00002CDE 751A                <1> 	JNZ	short CKST_EXIT		;  REPORT OK
  7103 00002CE0 B4CC                <1> 	MOV	AH,WRITE_FAULT
  7104 00002CE2 A820                <1> 	TEST	AL,ST_WRT_FLT		; CHECK FOR WRITE FAULT
  7105 00002CE4 7514                <1> 	JNZ	short CKST_EXIT
  7106 00002CE6 B4AA                <1> 	MOV	AH,NOT_RDY
  7107 00002CE8 A840                <1> 	TEST	AL,ST_READY		; CHECK FOR NOT READY
  7108 00002CEA 740E                <1> 	JZ	short CKST_EXIT
  7109 00002CEC B440                <1> 	MOV	AH,BAD_SEEK
  7110 00002CEE A810                <1> 	TEST	AL,ST_SEEK_COMPL	; CHECK FOR SEEK NOT COMPLETE
  7111 00002CF0 7408                <1> 	JZ	short CKST_EXIT
  7112 00002CF2 B411                <1> 	MOV	AH,DATA_CORRECTED
  7113 00002CF4 A804                <1> 	TEST	AL,ST_CORRCTD		; CHECK FOR CORRECTED ECC
  7114 00002CF6 7502                <1> 	JNZ	short CKST_EXIT
  7115 00002CF8 B400                <1> 	MOV	AH,0
  7116                              <1> CKST_EXIT:
  7117 00002CFA 8825[6F6B0000]      <1> 	MOV	[DISK_STATUS1],AH	; SET ERROR FLAG
  7118 00002D00 80FC11              <1> 	CMP	AH,DATA_CORRECTED	; KEEP GOING WITH DATA CORRECTED
  7119 00002D03 7403                <1> 	JZ	short CKST_EX1
  7120 00002D05 80FC00              <1> 	CMP	AH,0
  7121                              <1> CKST_EX1:
  7122 00002D08 C3                  <1> 	RETn
  7123                              <1> 
  7124                              <1> ;----------------------------------------
  7125                              <1> ;	CHECK FIXED DISK ERROR REGISTER :
  7126                              <1> ;----------------------------------------
  7127                              <1> CHECK_ER:
  7128                              <1> 	;MOV	DX, HF_PORT+1		; GET THE ERROR REGISTER
  7129 00002D09 668B15[C4650000]    <1> 	mov	dx, [HF_PORT]		;
  7130 00002D10 FEC2                <1> 	inc	dl
  7131 00002D12 EC                  <1> 	IN	AL,DX
  7132 00002D13 A2[666B0000]        <1> 	MOV	[HF_ERROR],AL
  7133 00002D18 53                  <1> 	PUSH	eBX ; 21/02/2015
  7134 00002D19 B908000000          <1> 	MOV	eCX,8			; TEST ALL 8 BITS
  7135 00002D1E D0E0                <1> CK1:	SHL	AL,1			; MOVE NEXT ERROR BIT TO CARRY
  7136 00002D20 7202                <1> 	JC	short CK2		; FOUND THE ERROR
  7137 00002D22 E2FA                <1> 	LOOP	CK1			; KEEP TRYING
  7138 00002D24 BB[B8650000]        <1> CK2:	MOV	eBX, ERR_TBL		; COMPUTE ADDRESS OF
  7139 00002D29 01CB                <1> 	ADD	eBX,eCX			; ERROR CODE
  7140                              <1> 	;;MOV	AH,BYTE [CS:BX]		; GET ERROR CODE
  7141                              <1> 	;mov	ah, [bx]
  7142 00002D2B 8A23                <1> 	mov	ah, [ebx] ; 21/02/2015	
  7143 00002D2D 8825[6F6B0000]      <1> CKEX:	MOV	[DISK_STATUS1],AH	; SAVE ERROR CODE
  7144 00002D33 5B                  <1> 	POP	eBX
  7145 00002D34 80FC00              <1> 	CMP	AH,0
  7146 00002D37 C3                  <1> 	RETn
  7147                              <1> 
  7148                              <1> ;--------------------------------------------------------
  7149                              <1> ; CHECK_DMA						:
  7150                              <1> ;  -CHECK ES:BX AND # SECTORS TO MAKE SURE THAT IT WILL :
  7151                              <1> ;   FIT WITHOUT SEGMENT OVERFLOW.			:
  7152                              <1> ;  -ES:BX HAS BEEN REVISED TO THE FORMAT SSSS:000X	:
  7153                              <1> ;  -OK IF # SECTORS < 80H (7FH IF LONG READ OR WRITE)	:
  7154                              <1> ;  -OK IF # SECTORS = 80H (7FH) AND BX <= 00H (04H)	:
  7155                              <1> ;  -ERROR OTHERWISE					:
  7156                              <1> ;--------------------------------------------------------
  7157                              <1> CHECK_DMA:
  7158                              <1> 	;PUSH	AX			; SAVE REGISTERS
  7159                              <1> 	; 24/12/2021
  7160 00002D38 50                  <1> 	push	eax
  7161 00002D39 66B80080            <1> 	MOV	AX,8000H		; AH = MAX # SECTORS AL = MAX OFFSET
  7162 00002D3D F645FE02            <1>         TEST    byte [CMD_BLOCK+6],ECC_MODE
  7163 00002D41 7404                <1> 	JZ	short CKD1
  7164 00002D43 66B8047F            <1> 	MOV	AX,7F04H		; ECC IS 4 MORE BYTES
  7165 00002D47 3A65F9              <1> CKD1:	CMP	AH, [CMD_BLOCK+1] 	; NUMBER OF SECTORS
  7166 00002D4A 7706                <1> 	JA	short CKDOK		; IT WILL FIT
  7167 00002D4C 7207                <1> 	JB	short CKDERR		; TOO MANY
  7168 00002D4E 38D8                <1> 	CMP	AL,BL			; CHECK OFFSET ON MAX SECTORS
  7169 00002D50 7203                <1> 	JB	short CKDERR		; ERROR
  7170 00002D52 F8                  <1> CKDOK:	CLC				; CLEAR CARRY
  7171                              <1> 	;POP	AX
  7172                              <1> 	; 24/12/2021
  7173 00002D53 58                  <1> 	pop	eax
  7174 00002D54 C3                  <1> 	RETn				; NORMAL RETURN
  7175 00002D55 F9                  <1> CKDERR: STC				; INDICATE ERROR
  7176 00002D56 C605[6F6B0000]09    <1>         MOV     byte [DISK_STATUS1],DMA_BOUNDARY
  7177                              <1> 	;POP	AX
  7178                              <1> 	; 24/12/2021
  7179 00002D5D 58                  <1> 	pop	eax	
  7180 00002D5E C3                  <1> 	RETn
  7181                              <1> 
  7182                              <1> ;----------------------------------------
  7183                              <1> ;	SET UP ES:BX-> DISK PARMS	:
  7184                              <1> ;----------------------------------------
  7185                              <1> 					
  7186                              <1> ; INPUT -> DL = 0 based drive number
  7187                              <1> ; OUTPUT -> ES:BX = disk parameter table address
  7188                              <1> 
  7189                              <1> GET_VEC:
  7190                              <1> 	;SUB	AX,AX			; GET DISK PARAMETER ADDRESS
  7191                              <1> 	;MOV	ES,AX
  7192                              <1> 	;TEST	DL,1
  7193                              <1> 	;JZ	short GV_0
  7194                              <1> ;	LES	BX,[HF1_TBL_VEC] 	; ES:BX -> DRIVE PARAMETERS
  7195                              <1> ;	JMP	SHORT GV_EXIT
  7196                              <1> ;GV_0:
  7197                              <1> ;	LES	BX,[HF_TBL_VEC]		; ES:BX -> DRIVE PARAMETERS
  7198                              <1> ;
  7199                              <1> 	;xor	bh, bh
  7200 00002D5F 31DB                <1> 	xor	ebx, ebx
  7201 00002D61 88D3                <1> 	mov	bl, dl
  7202                              <1> 	;;02/01/2015
  7203                              <1> 	;;shl	bl, 1			; port address offset
  7204                              <1> 	;;mov	ax, [bx+hd_ports]	; Base port address (1F0h, 170h)
  7205                              <1> 	;;shl	bl, 1			; dpt pointer offset
  7206 00002D63 C0E302              <1> 	shl	bl, 2	;;
  7207                              <1> 	;add	bx, HF_TBL_VEC		; Disk parameter table pointer
  7208 00002D66 81C3[746B0000]      <1> 	add	ebx, HF_TBL_VEC ; 21/02/2015
  7209                              <1> 	;push	word [bx+2]		; dpt segment
  7210                              <1> 	;pop	es
  7211                              <1> 	;mov	bx, [bx]		; dpt offset
  7212 00002D6C 8B1B                <1> 	mov	ebx, [ebx]		
  7213                              <1> ;GV_EXIT:
  7214 00002D6E C3                  <1> 	RETn
  7215                              <1> 
  7216                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7217                              <1> hdc1_int: ; 21/02/2015
  7218                              <1> ;--- HARDWARE INT 76H -- ( IRQ LEVEL  14 ) ----------------------
  7219                              <1> ;								:
  7220                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7221                              <1> ;								:
  7222                              <1> ;----------------------------------------------------------------
  7223                              <1> 
  7224                              <1> ; 22/12/2014
  7225                              <1> ; IBM PC-XT Model 286 System BIOS Source Code - DISK.ASM (HD_INT)
  7226                              <1> ;	 '11/15/85'
  7227                              <1> ; AWARD BIOS 1999 (D1A0622) 
  7228                              <1> ;	Source Code - ATORGS.ASM (INT_HDISK, INT_HDISK1)
  7229                              <1> 
  7230                              <1> ;int_76h:
  7231                              <1> HD_INT:
  7232                              <1> 	;push	ax
  7233                              <1> 	; 24/12/2021
  7234 00002D6F 50                  <1> 	push	eax
  7235 00002D70 1E                  <1> 	push	ds
  7236                              <1> 	;CALL	DDS
  7237                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7238 00002D71 66B81000            <1> 	mov	ax, KDATA
  7239 00002D75 8ED8                <1> 	mov 	ds, ax
  7240                              <1> 	;
  7241                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7242                              <1>         ;mov     byte [CS:HF_INT_FLAG], 0FFh
  7243 00002D77 C605[676B0000]FF    <1> 	mov	byte [HF_INT_FLAG], 0FFh
  7244                              <1> 	;
  7245                              <1> 	;push	dx
  7246                              <1> 	; 24/12/2021
  7247 00002D7E 52                  <1> 	push	edx
  7248 00002D7F 66BAF701            <1> 	mov	dx, HDC1_BASEPORT+7	; Status Register (1F7h)
  7249                              <1> 					; Clear Controller
  7250                              <1> Clear_IRQ1415:				; (Award BIOS - 1999)
  7251 00002D83 EC                  <1> 	in	al, dx			;
  7252                              <1> 	;pop	dx
  7253                              <1> 	; 24/12/2021
  7254 00002D84 5A                  <1> 	pop	edx
  7255                              <1> 	NEWIODELAY
  2154 00002D85 E6EB                <2>  out 0EBh,al
  7256                              <1> 	;
  7257 00002D87 B020                <1> 	MOV	AL,EOI			; NON-SPECIFIC END OF INTERRUPT
  7258 00002D89 E6A0                <1> 	OUT	INTB00,AL		; FOR CONTROLLER #2
  7259                              <1> 	;JMP	$+2			; WAIT
  7260                              <1> 	NEWIODELAY
  2154 00002D8B E6EB                <2>  out 0EBh,al
  7261 00002D8D E620                <1> 	OUT	INTA00,AL		; FOR CONTROLLER #1
  7262 00002D8F 1F                  <1> 	pop	ds
  7263                              <1> 	;STI				; RE-ENABLE INTERRUPTS
  7264                              <1> 	;MOV	AX,9100H		; DEVICE POST
  7265                              <1> 	;INT	15H			;  INTERRUPT
  7266                              <1> irq15_iret: ; 25/02/2015
  7267                              <1> 	;pop	ax
  7268                              <1> 	; 24/12/2021
  7269 00002D90 58                  <1> 	pop	eax
  7270 00002D91 CF                  <1> 	iretd			; RETURN FROM INTERRUPT
  7271                              <1> 
  7272                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  7273                              <1> hdc2_int: ; 21/02/2015
  7274                              <1> ;++++ HARDWARE INT 77H ++ ( IRQ LEVEL  15 ) +++++++++++++++++++++
  7275                              <1> ;								:
  7276                              <1> ;	FIXED DISK INTERRUPT ROUTINE				:
  7277                              <1> ;								:
  7278                              <1> ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7279                              <1> 
  7280                              <1> ;int_77h:
  7281                              <1> HD1_INT:
  7282                              <1> 	;push	ax
  7283                              <1> 	; 24/12/2021
  7284 00002D92 50                  <1> 	push	eax
  7285                              <1> 	; Check if that is a spurious IRQ (from slave PIC)
  7286                              <1> 	; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  7287 00002D93 B00B                <1> 	mov	al, 0Bh  ; In-Service Register
  7288 00002D95 E6A0                <1> 	out	0A0h, al
  7289 00002D97 EB00                <1>         jmp short $+2
  7290 00002D99 EB00                <1> 	jmp short $+2
  7291 00002D9B E4A0                <1> 	in	al, 0A0h
  7292 00002D9D 2480                <1> 	and 	al, 80h ; bit 7 (is it real IRQ 15 or fake?)
  7293 00002D9F 74EF                <1> 	jz	short irq15_iret ; Fake (spurious)IRQ, do not send EOI)
  7294                              <1> 	;
  7295 00002DA1 1E                  <1> 	push	ds
  7296                              <1> 	;CALL	DDS
  7297                              <1> 	; 21/02/2015 (32 bit, 386 pm modification)
  7298 00002DA2 66B81000            <1> 	mov	ax, KDATA
  7299 00002DA6 8ED8                <1> 	mov 	ds, ax
  7300                              <1> 	;
  7301                              <1> 	;;MOV	@HF_INT_FLAG,0FFH	; ALL DONE
  7302                              <1>         ;or	byte [CS:HF_INT_FLAG],0C0h 
  7303 00002DA8 800D[676B0000]C0    <1> 	or	byte [HF_INT_FLAG], 0C0h
  7304                              <1> 	;
  7305                              <1> 	;push	dx
  7306                              <1> 	; 24/12/2021
  7307 00002DAF 52                  <1> 	push	edx
  7308 00002DB0 66BA7701            <1> 	mov	dx, HDC2_BASEPORT+7	; Status Register (177h)
  7309                              <1> 					; Clear Controller (Award BIOS 1999)
  7310 00002DB4 EBCD                <1> 	jmp	short Clear_IRQ1415
  7311                              <1> 
  7312                              <1> ;%include 'diskdata.inc' ; 11/03/2015
  7313                              <1> ;%include 'diskbss.inc' ; 11/03/2015
  7314                              <1> 
  7315                              <1> ;////////////////////////////////////////////////////////////////////
  7316                              <1> ;; END OF DISK I/O SYTEM ///
  2093                                  %include 'memory.inc'  ; 09/03/2015
  2094                              <1> ; MEMORY.ASM - Retro UNIX 386 v1.1 MEMORY MANAGEMENT FUNCTIONS (PROCEDURES)
  2095                              <1> ; Retro UNIX 386 v1.1 Kernel (unix386.s, v0.2.1.1) - MEMORY.INC
  2096                              <1> ; Last Modification: 31/12/2021
  2097                              <1> ;
  2098                              <1> ; Source code for NASM - Netwide Assembler (2.15)
  2099                              <1> 
  2100                              <1> ; ///////// MEMORY MANAGEMENT FUNCTIONS (PROCEDURES) ///////////////
  2101                              <1> 
  2102                              <1> ;;04/11/2014 (unix386.s)	
  2103                              <1> ;PDE_A_PRESENT	equ 1		; Present flag for PDE
  2104                              <1> ;PDE_A_WRITE	equ 2		; Writable (write permission) flag
  2105                              <1> ;PDE_A_USER	equ 4		; User (non-system/kernel) page flag
  2106                              <1> ;;
  2107                              <1> ;PTE_A_PRESENT	equ 1		; Present flag for PTE (bit 0)
  2108                              <1> ;PTE_A_WRITE	equ 2		; Writable (write permission) flag (bit 1)
  2109                              <1> ;PTE_A_USER	equ 4		; User (non-system/kernel) page flag (bit 2)
  2110                              <1> ;PTE_A_ACCESS   equ 32		; Accessed flag (bit 5) ; 09/03/2015
  2111                              <1> 
  2112                              <1> ; 27/04/2015
  2113                              <1> ; 09/03/2015
  2114                              <1> PAGE_SIZE 	equ 4096	; page size in bytes
  2115                              <1> PAGE_SHIFT 	equ 12		; page table shift count
  2116                              <1> PAGE_D_SHIFT 	equ 22 ; 12+10	; page directory shift count
  2117                              <1> PAGE_OFF	equ 0FFFh	; 12 bit byte offset in page frame
  2118                              <1> PTE_MASK 	equ 03FFh	; page table entry mask
  2119                              <1> PTE_DUPLICATED  equ 200h	; duplicated page sign (AVL bit 0)
  2120                              <1> PDE_A_CLEAR	equ 0F000h	; to clear PDE attribute bits
  2121                              <1> PTE_A_CLEAR	equ 0F000h	; to clear PTE attribute bits
  2122                              <1> LOGIC_SECT_SIZE equ 512		; logical sector size
  2123                              <1> ERR_MAJOR_PF	equ 0E0h	; major error: page fault
  2124                              <1> ; 15/10/2016 (TRDOS 386 v2)
  2125                              <1> ERR_MINOR_IM	equ 4 ;15/10/2016 (1->4); insufficient (out of) memory
  2126                              <1> ERR_MINOR_PV	equ 6 ;15/10/2016 (3->6); protection violation
  2127                              <1> SWP_DISK_READ_ERR 	   equ 40
  2128                              <1> SWP_DISK_NOT_PRESENT_ERR   equ 41
  2129                              <1> SWP_SECTOR_NOT_PRESENT_ERR equ 42
  2130                              <1> SWP_NO_FREE_SPACE_ERR      equ 43
  2131                              <1> SWP_DISK_WRITE_ERR         equ 44
  2132                              <1> SWP_NO_PAGE_TO_SWAP_ERR    equ 45
  2133                              <1> PTE_A_ACCESS_BIT equ 5	; Bit 5 (accessed flag)        
  2134                              <1> SECTOR_SHIFT     equ 3	; sector shift (to convert page block number)
  2135                              <1> ; 10/06/2021 (Retro UNIX 386 v2)
  2136                              <1> ; 12/07/2016 (TRDOS 386 v2) 
  2137                              <1> PTE_SHARED	 equ 400h		; AVL bit 1, direct memory access bit	
  2138                              <1> 					; (Indicates that the page is not allocated
  2139                              <1> 					; for the process, it is a shared or system
  2140                              <1>                                         ; page, it must not be deallocated!)
  2141                              <1> ; 14/12/2020
  2142                              <1> ; (Linear Frame Buffer - video memory mark : AVL bit 1, outside M.A.T.)
  2143                              <1> PDE_EXTERNAL	equ 400h	; Page directory entry for external memory blocks
  2144                              <1> PTE_EXTERNAL	equ 400h	; Allocated kernel pages for Linear Frame Buffer
  2145                              <1> 				; (Out of memory allocation table)	
  2146                              <1> ;
  2147                              <1> ;; Retro Unix 386 v1 - paging method/principles
  2148                              <1> ;;
  2149                              <1> ;; 10/10/2014
  2150                              <1> ;; RETRO UNIX 386 v1 - PAGING METHOD/PRINCIPLES
  2151                              <1> ;;
  2152                              <1> ;; KERNEL PAGE MAP: 1 to 1 physical memory page map
  2153                              <1> ;;	(virtual address = physical address)
  2154                              <1> ;; KERNEL PAGE TABLES:
  2155                              <1> ;;	Kernel page directory and all page tables are
  2156                              <1> ;;	on memory as initialized, as equal to physical memory
  2157                              <1> ;;	layout. Kernel pages can/must not be swapped out/in.
  2158                              <1> ;;
  2159                              <1> ;;	what for: User pages may be swapped out, when accessing
  2160                              <1> ;;	a page in kernel/system mode, if it would be swapped out,
  2161                              <1> ;;	kernel would have to swap it in! But it is also may be
  2162                              <1> ;;	in use by a user process. (In system/kernel mode
  2163                              <1> ;;	kernel can access all memory pages even if they are
  2164                              <1> ;;	reserved/allocated for user processes. Swap out/in would
  2165                              <1> ;;	cause conflicts.) 
  2166                              <1> ;;	
  2167                              <1> ;;	As result of these conditions,
  2168                              <1> ;;	all kernel pages must be initialized as equal to 
  2169                              <1> ;;	physical layout for preventing page faults. 
  2170                              <1> ;;	Also, calling "allocate page" procedure after
  2171                              <1> ;;	a page fault can cause another page fault (double fault)
  2172                              <1> ;;	if all kernel page tables would not be initialized.
  2173                              <1> ;;
  2174                              <1> ;;	[first_page] = Beginning of users space, as offset to 
  2175                              <1> ;;	memory allocation table. (double word aligned)
  2176                              <1> ;;
  2177                              <1> ;;	[next_page] = first/next free space to be searched
  2178                              <1> ;;	as offset to memory allocation table. (dw aligned)
  2179                              <1> ;;
  2180                              <1> ;;	[last_page] = End of memory (users space), as offset
  2181                              <1> ;;	to memory allocation table. (double word aligned)
  2182                              <1> ;;
  2183                              <1> ;; USER PAGE TABLES:
  2184                              <1> ;;	Demand paging (& 'copy on write' allocation method) ...
  2185                              <1> ;;		'ready only' marked copies of the 
  2186                              <1> ;;		parent process's page table entries (for
  2187                              <1> ;;		same physical memory).
  2188                              <1> ;;		(A page will be copied to a new page after
  2189                              <1> ;;		 if it causes R/W page fault.)
  2190                              <1> ;;
  2191                              <1> ;;	Every user process has own (different)
  2192                              <1> ;;	page directory and page tables.	
  2193                              <1> ;;
  2194                              <1> ;;	Code starts at virtual address 0, always.
  2195                              <1> ;;	(Initial value of EIP is 0 in user mode.)
  2196                              <1> ;;	(Programs can be written/developed as simple
  2197                              <1> ;;	 flat memory programs.)
  2198                              <1> ;;
  2199                              <1> ;; MEMORY ALLOCATION STRATEGY:
  2200                              <1> ;;	Memory page will be allocated by kernel only 
  2201                              <1> ;;		(in kernel/system mode only).
  2202                              <1> ;;	* After a
  2203                              <1> ;;	  - 'not present' page fault
  2204                              <1> ;;	  - 'writing attempt on read only page' page fault 	 	
  2205                              <1> ;;	* For loading (opening, reading) a file or disk/drive
  2206                              <1> ;;	* As responce to 'allocate additional memory blocks' 
  2207                              <1> ;;	  request by running process.
  2208                              <1> ;;	* While creating a process, allocating a new buffer,
  2209                              <1> ;;	  new page tables etc.
  2210                              <1> ;;
  2211                              <1> ;;	At first,
  2212                              <1> ;;	- 'allocate page' procedure will be called;
  2213                              <1> ;,	   if it will return with a valid (>0) physical address
  2214                              <1> ;;	   (that means the relevant M.A.T. bit has been RESET)	
  2215                              <1> ;;	   relevant memory page/block will be cleared (zeroed).
  2216                              <1> ;;	- 'allocate page' will be called for allocating page
  2217                              <1> ;;	   directory, page table and running space (data/code).
  2218                              <1> ;;	- every successful 'allocate page' call will decrease
  2219                              <1> ;;	  'free_pages' count (pointer).
  2220                              <1> ;;	- 'out of (insufficient) memory error' will be returned
  2221                              <1> ;;	  if 'free_pages' points to a ZERO.
  2222                              <1> ;;	- swapping out and swapping in (if it is not a new page)
  2223                              <1> ;;	  procedures will be called as responce to 'out of memory'
  2224                              <1> ;;	  error except errors caused by attribute conflicts.
  2225                              <1> ;;	 (swapper functions)	 
  2226                              <1> ;;					
  2227                              <1> ;;	At second,
  2228                              <1> ;;	- page directory entry will be updated then page table
  2229                              <1> ;;	  entry will be updated.		
  2230                              <1> ;;
  2231                              <1> ;; MEMORY ALLOCATION TABLE FORMAT:
  2232                              <1> ;;	- M.A.T. has a size according to available memory as
  2233                              <1> ;;	  follows:
  2234                              <1> ;;		  - 1 (allocation) bit per 1 page (4096 bytes)
  2235                              <1> ;;		  - a bit with value of 0 means allocated page
  2236                              <1> ;;		  - a bit with value of 1 means a free page
  2237                              <1> ;,	- 'free_pages' pointer holds count of free pages
  2238                              <1> ;;	  depending on M.A.T.
  2239                              <1> ;;		(NOTE: Free page count will not be checked
  2240                              <1> ;;		again -on M.A.T.- after initialization. 
  2241                              <1> ;;		Kernel will trust on initial count.)
  2242                              <1> ;,	- 'free_pages' count will be decreased by allocation
  2243                              <1> ;;	  and it will be increased by deallocation procedures.
  2244                              <1> ;;	
  2245                              <1> ;;	- Available memory will be calculated during
  2246                              <1> ;;	  the kernel's initialization stage (in real mode).
  2247                              <1> ;;	  Memory allocation table and kernel page tables 
  2248                              <1> ;;	  will be formatted/sized as result of available
  2249                              <1> ;;	  memory calculation before paging is enabled.
  2250                              <1> ;;
  2251                              <1> ;; For 4GB Available/Present Memory: (max. possible memory size)
  2252                              <1> ;;	- Memory Allocation Table size will be 128 KB.
  2253                              <1> ;;	- Memory allocation for kernel page directory size 
  2254                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2255                              <1> ;;	  for page tables)
  2256                              <1> ;;	- Memory allocation for kernel page tables (1024 tables)
  2257                              <1> ;;	  is 4 MB (1024*4*1024 bytes).
  2258                              <1> ;;	- User (available) space will be started 
  2259                              <1> ;;	  at 6th MB of the memory (after 1MB+4MB).
  2260                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2261                              <1> ;;	  memory allocation table and kernel's page directory
  2262                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2263                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2264                              <1> ;; 	  for buffers.
  2265                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2266                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2267                              <1> ;;	- Kernel page tables start at 100000h (2nd MB)
  2268                              <1> ;;
  2269                              <1> ;; For 1GB Available Memory:
  2270                              <1> ;;	- Memory Allocation Table size will be 32 KB.
  2271                              <1> ;;	- Memory allocation for kernel page directory size 
  2272                              <1> ;;	  is always 4 KB. (in addition to total allocation size
  2273                              <1> ;;	  for page tables)
  2274                              <1> ;;	- Memory allocation for kernel page tables (256 tables)
  2275                              <1> ;;	  is 1 MB (256*4*1024 bytes).
  2276                              <1> ;;	- User (available) space will be started 
  2277                              <1> ;;	  at 3th MB of the memory (after 1MB+1MB).
  2278                              <1> ;;	- The first 640 KB is for kernel's itself plus
  2279                              <1> ;;	  memory allocation table and kernel's page directory
  2280                              <1> ;;	  (D0000h-EFFFFh may be used as kernel space...)	
  2281                              <1> ;;	- B0000h to B7FFFh address space (32 KB) will be used
  2282                              <1> ;; 	  for buffers.
  2283                              <1> ;;	- ROMBIOS, VIDEO BUFFER and VIDEO ROM space are reserved.
  2284                              <1> ;,	  (A0000h-AFFFFh, C0000h-CFFFFh, F0000h-FFFFFh)
  2285                              <1> ;;	- Kernel page tables start at 100000h (2nd MB).	
  2286                              <1> ;;
  2287                              <1> ;;
  2288                              <1> 
  2289                              <1> ;;************************************************************************************
  2290                              <1> ;; 
  2291                              <1> ;; RETRO UNIX 386 v1 - Paging (Method for Copy On Write paging principle)
  2292                              <1> ;; DEMAND PAGING - PARENT&CHILD PAGE TABLE DUPLICATION PRINCIPLES (23/04/2015)
  2293                              <1> 
  2294                              <1> ;; Main factor: "sys fork" system call 
  2295                              <1> ;;	
  2296                              <1> ;; 		FORK
  2297                              <1> ;;                      |----> parent - duplicated PTEs, read only pages
  2298                              <1> ;;  writable pages ---->|
  2299                              <1> ;;                      |----> child - duplicated PTEs, read only pages
  2300                              <1> ;; 
  2301                              <1> ;; AVL bit (0) of Page Table Entry is used as duplication sign 
  2302                              <1> ;; 
  2303                              <1> ;; AVL Bit 0 [PTE Bit 9] = 'Duplicated PTE belongs to child' sign/flag (if it is set)
  2304                              <1> ;; Note: Dirty bit (PTE bit 6) may be used instead of AVL bit 0 (PTE bit 9)
  2305                              <1> ;;       -while R/W bit is 0-. 
  2306                              <1> ;; 
  2307                              <1> ;; Duplicate page tables with writable pages (the 1st sys fork in the process):
  2308                              <1> ;; # Parent's Page Table Entries are updated to point same pages as read only, 
  2309                              <1> ;;   as duplicated PTE bit  -AVL bit 0, PTE bit 9- are reset/clear.
  2310                              <1> ;; # Then Parent's Page Table is copied to Child's Page Table.
  2311                              <1> ;; # Child's Page Table Entries are updated as duplicated child bit
  2312                              <1> ;;   -AVL bit 0, PTE bit 9- is set.	  
  2313                              <1> ;; 
  2314                              <1> ;; Duplicate page tables with read only pages (several sys fork system calls):
  2315                              <1> ;; # Parent's read only pages are copied to new child pages. 
  2316                              <1> ;;   Parent's PTE attributes are not changed.
  2317                              <1> ;;   (Because, there is another parent-child fork before this fork! We must not
  2318                              <1> ;;    destroy/mix previous fork result).
  2319                              <1> ;; # Child's Page Table Entries (which are corresponding to Parent's 
  2320                              <1> ;;   read only pages) are set as writable (while duplicated PTE bit is clear). 
  2321                              <1> ;; # Parent's PTEs with writable page attribute are updated to point same pages 
  2322                              <1> ;;   as read only, (while) duplicated PTE bit is reset (clear).
  2323                              <1> ;; # Parent's Page Table Entries (with writable page attribute) are duplicated 
  2324                              <1> ;;   as Child's Page Table Entries without copying actual page.
  2325                              <1> ;; # Child 's Page Table Entries (which are corresponding to Parent's writable 
  2326                              <1> ;;   pages) are updated as duplicated PTE bit (AVL bit 0, PTE bit 9- is set.
  2327                              <1> ;; 
  2328                              <1> ;; !? WHAT FOR (duplication after duplication):
  2329                              <1> ;; In UNIX method for sys fork (a typical 'fork' application in /etc/init)
  2330                              <1> ;; program/executable code continues from specified location as child process, 
  2331                              <1> ;; returns back previous code location as parent process, every child after 
  2332                              <1> ;; every sys fork uses last image of code and data just prior the fork.
  2333                              <1> ;; Even if the parent code changes data, the child will not see the changed data 
  2334                              <1> ;; after the fork. In Retro UNIX 8086 v1, parent's process segment (32KB)
  2335                              <1> ;; was copied to child's process segment (all of code and data) according to
  2336                              <1> ;; original UNIX v1 which copies all of parent process code and data -core- 
  2337                              <1> ;; to child space -core- but swaps that core image -of child- on to disk.
  2338                              <1> ;; If I (Erdogan Tan) would use a method of to copy parent's core
  2339                              <1> ;; (complete running image of parent process) to the child process; 
  2340                              <1> ;; for big sizes, i would force Retro UNIX 386 v1 to spend many memory pages 
  2341                              <1> ;; and times only for a sys fork. (It would excessive reservation for sys fork,
  2342                              <1> ;; because sys fork usually is prior to sys exec; sys exec always establishes
  2343                              <1> ;; a new/fresh core -running space-, by clearing all code/data content). 
  2344                              <1> ;; 'Read Only' page flag ensures page fault handler is needed only for a few write
  2345                              <1> ;; attempts between sys fork and sys exec, not more... (I say so by thinking 
  2346                              <1> ;; of "/etc/init" content, specially.) sys exec will clear page tables and
  2347                              <1> ;; new/fresh pages will be used to load and run new executable/program.
  2348                              <1> ;; That is what for i have preferred "copy on write", "duplication" method
  2349                              <1> ;; for sharing same read only pages between parent and child processes.
  2350                              <1> ;; That is a pitty i have to use new private flag (AVL bit 0, "duplicated PTE 
  2351                              <1> ;; belongs to child" sign) for cooperation on duplicated pages between a parent 
  2352                              <1> ;; and it's child processes; otherwise parent process would destroy data belongs
  2353                              <1> ;; to its child or vice versa; or some pages would remain unclaimed 
  2354                              <1> ;; -deallocation problem-.
  2355                              <1> ;; Note: to prevent conflicts, read only pages must not be swapped out... 
  2356                              <1> ;; 
  2357                              <1> ;; WHEN PARENT TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2358                              <1> ;; # Page fault handler will do those:
  2359                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2360                              <1> ;;   - If it is reset/clear, there is a child uses same page.
  2361                              <1> ;;   - Parent's read only page -previous page- is copied to a new writable page. 
  2362                              <1> ;;   - Parent's PTE is updated as writable page, as unique page (AVL=0)
  2363                              <1> ;;   - (Page fault handler whill check this PTE later, if child process causes to
  2364                              <1> ;;     page fault due to write attempt on read only page. Of course, the previous 
  2365                              <1> ;;     read only page will be converted to writable and unique page which belongs
  2366                              <1> ;;     to child process.)	
  2367                              <1> ;; WHEN CHILD TRIES TO WRITE IT'S READ ONLY (DUPLICATED) PAGE:
  2368                              <1> ;; # Page fault handler will do those:
  2369                              <1> ;;   - 'Duplicated PTE' flag (PTE bit 9) is checked (on the failed PTE).
  2370                              <1> ;;   - If it is set, there is a parent uses -or was using- same page.
  2371                              <1> ;;   - Same PTE address within parent's page table is checked if it has same page
  2372                              <1> ;;     address or not. 
  2373                              <1> ;;   - If parent's PTE has same address, child will continue with a new writable page.
  2374                              <1> ;;     Parent's PTE will point to same (previous) page as writable, unique (AVL=0).	
  2375                              <1> ;;   - If parent's PTE has different address, child will continue with it's 
  2376                              <1> ;;     own/same page but read only flag (0) will be changed to writable flag (1) and
  2377                              <1> ;;     'duplicated PTE (belongs to child)' flag/sign will be cleared/reset. 	  	
  2378                              <1> ;; 
  2379                              <1> ;; NOTE: When a child process is terminated, read only flags of parent's page tables
  2380                              <1> ;;       will be set as writable (and unique) in case of child process was using 
  2381                              <1> ;;       same pages with duplicated child PTE sign... Depending on sys fork and 
  2382                              <1> ;;       duplication method details, it is not possible multiple child processes
  2383                              <1> ;;       were using same page with duplicated PTEs.
  2384                              <1> ;; 
  2385                              <1> ;;************************************************************************************   
  2386                              <1> 
  2387                              <1> ;; 08/10/2014
  2388                              <1> ;; 11/09/2014 - Retro UNIX 386 v1 PAGING (further) draft
  2389                              <1> ;;		by Erdogan Tan (Based on KolibriOS 'memory.inc')
  2390                              <1> 
  2391                              <1> ;; 'allocate_page' code is derived and modified from KolibriOS
  2392                              <1> ;; 'alloc_page' procedure in 'memory.inc' 
  2393                              <1> ;; (25/08/2014, Revision: 5057) file 
  2394                              <1> ;; by KolibriOS Team (2004-2012)
  2395                              <1> 
  2396                              <1> allocate_page:
  2397                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2398                              <1> 	; 01/07/2015
  2399                              <1> 	; 05/05/2015
  2400                              <1> 	; 30/04/2015
  2401                              <1> 	; 16/10/2014
  2402                              <1> 	; 08/10/2014
  2403                              <1> 	; 09/09/2014 (Retro UNIX 386 v1 - beginning)
  2404                              <1> 	;
  2405                              <1> 	; INPUT -> none
  2406                              <1> 	;
  2407                              <1> 	; OUTPUT ->
  2408                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2409                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is RESET)
  2410                              <1> 	;
  2411                              <1> 	;	CF = 1 and EAX = 0 
  2412                              <1> 	; 		   if there is not a free page to be allocated	
  2413                              <1> 	;
  2414                              <1> 	; Modified Registers -> none (except EAX)
  2415                              <1> 	;
  2416 00002DB6 A1[E06A0000]        <1> 	mov	eax, [free_pages]
  2417 00002DBB 21C0                <1> 	and	eax, eax
  2418 00002DBD 7438                <1> 	jz	short out_of_memory
  2419                              <1> 	;
  2420 00002DBF 53                  <1> 	push	ebx
  2421 00002DC0 51                  <1> 	push	ecx
  2422                              <1> 	;
  2423 00002DC1 BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table offset
  2424 00002DC6 89D9                <1> 	mov	ecx, ebx
  2425                              <1>  				     ; NOTE: 32 (first_page) is initial
  2426                              <1> 				     ; value of [next_page].
  2427                              <1> 				     ; It points to the first available
  2428                              <1> 				     ; page block for users (ring 3) ...	
  2429                              <1> 				     ; (MAT offset 32 = 1024/32)	
  2430                              <1> 				     ; (at the of the first 4 MB)		
  2431 00002DC8 031D[E46A0000]      <1> 	add	ebx, [next_page] ; Free page searching starts from here
  2432                              <1> 				 ; next_free_page >> 5
  2433 00002DCE 030D[E86A0000]      <1> 	add	ecx, [last_page] ; Free page searching ends here
  2434                              <1> 				 ; (total_pages - 1) >> 5
  2435                              <1> al_p_scan:
  2436 00002DD4 39CB                <1> 	cmp	ebx, ecx
  2437 00002DD6 770A                <1> 	ja	short al_p_notfound
  2438                              <1> 	;
  2439                              <1> 	; 01/07/2015
  2440                              <1> 	; AMD64 Architecture Programmers Manual
  2441                              <1> 	; Volume 3:
  2442                              <1> 	; General-Purpose and System Instructions
  2443                              <1> 	;
  2444                              <1> 	; BSF - Bit Scan Forward
  2445                              <1> 	;
  2446                              <1> 	;   Searches the value in a register or a memory location
  2447                              <1> 	;   (second operand) for the least-significant set bit. 
  2448                              <1> 	;   If a set bit is found, the instruction clears the zero flag (ZF)
  2449                              <1> 	;   and stores the index of the least-significant set bit in a destination
  2450                              <1> 	;   register (first operand). If the second operand contains 0, 
  2451                              <1> 	;   the instruction sets ZF to 1 and does not change the contents of the 
  2452                              <1> 	;   destination register. The bit index is an unsigned offset from bit 0 
  2453                              <1> 	;   of the searched value
  2454                              <1> 	;
  2455 00002DD8 0FBC03              <1> 	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  2456                              <1> 			   ; Clear ZF if a bit is found set (1) and 
  2457                              <1> 			   ; loads the destination with an index to
  2458                              <1> 			   ; first set bit. (0 -> 31) 
  2459                              <1> 			   ; Sets ZF to 1 if no bits are found set.
  2460 00002DDB 751C                <1> 	jnz	short al_p_found ; ZF = 0 -> a free page has been found
  2461                              <1> 			 ;
  2462                              <1> 			 ; NOTE:  a Memory Allocation Table bit 
  2463                              <1> 			 ;	  with value of 1 means 
  2464                              <1> 			 ;	  the corresponding page is free 
  2465                              <1> 			 ;	  (Retro UNIX 386 v1 feature only!)
  2466 00002DDD 83C304              <1> 	add	ebx, 4
  2467                              <1> 			 ; We return back for searching next page block
  2468                              <1> 			 ; NOTE: [free_pages] is not ZERO; so, 
  2469                              <1> 			 ;	 we always will find at least 1 free page here.
  2470 00002DE0 EBF2                <1>         jmp     short al_p_scan
  2471                              <1> 	;
  2472                              <1> al_p_notfound:
  2473 00002DE2 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2474 00002DE8 890D[E46A0000]      <1> 	mov	[next_page], ecx ; next/first free page = last page 
  2475                              <1> 				 ; (deallocate_page procedure will change it)
  2476 00002DEE 31C0                <1> 	xor	eax, eax
  2477 00002DF0 A3[E06A0000]        <1> 	mov	[free_pages], eax ; 0
  2478 00002DF5 59                  <1> 	pop	ecx
  2479 00002DF6 5B                  <1> 	pop	ebx
  2480                              <1> 	;
  2481                              <1> ; 24/12/2021
  2482                              <1> ; ('swap_out' procedure call is disabled)
  2483                              <1> 
  2484                              <1> out_of_memory:
  2485                              <1> ;	call	swap_out
  2486                              <1> ;	jnc	short al_p_ok  ; [free_pages] = 0, re-allocation by swap_out
  2487                              <1> ;	;
  2488                              <1> ;	sub 	eax, eax ; 0
  2489 00002DF7 F9                  <1> 	stc
  2490 00002DF8 C3                  <1> 	retn
  2491                              <1> 
  2492                              <1> al_p_found:
  2493 00002DF9 89D9                <1> 	mov	ecx, ebx
  2494 00002DFB 81E900001000        <1> 	sub	ecx, MEM_ALLOC_TBL
  2495 00002E01 890D[E46A0000]      <1> 	mov	[next_page], ecx ; Set first free page searching start
  2496                              <1> 				 ; address/offset (to the next)
  2497 00002E07 FF0D[E06A0000]      <1>         dec     dword [free_pages] ; 1 page has been allocated (X = X-1) 
  2498                              <1> 	;
  2499 00002E0D 0FB303              <1> 	btr	[ebx], eax	 ; The destination bit indexed by the source value
  2500                              <1> 				 ; is copied into the Carry Flag and then cleared
  2501                              <1> 				 ; in the destination.
  2502                              <1> 				 ;
  2503                              <1> 				 ; Reset the bit which is corresponding to the 
  2504                              <1> 				 ; (just) allocated page.
  2505                              <1> 	; 01/07/2015 (4*8 = 32, 1 allocation byte = 8 pages)	
  2506 00002E10 C1E103              <1> 	shl	ecx, 3		 ; (page block offset * 32) + page index
  2507 00002E13 01C8                <1> 	add	eax, ecx	 ; = page number
  2508 00002E15 C1E00C              <1> 	shl	eax, 12		 ; physical address of the page (flat/real value)
  2509                              <1> 	; EAX = physical address of memory page
  2510                              <1> 	;
  2511                              <1> 	; NOTE: The relevant page directory and page table entry will be updated
  2512                              <1> 	;       according to this EAX value...
  2513 00002E18 59                  <1> 	pop	ecx
  2514 00002E19 5B                  <1> 	pop	ebx
  2515                              <1> al_p_ok:
  2516 00002E1A C3                  <1> 	retn
  2517                              <1> 
  2518                              <1> make_page_dir:
  2519                              <1> 	; 18/04/2015
  2520                              <1> 	; 12/04/2015
  2521                              <1> 	; 23/10/2014
  2522                              <1> 	; 16/10/2014
  2523                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2524                              <1> 	;
  2525                              <1> 	; INPUT ->
  2526                              <1> 	;	none
  2527                              <1> 	; OUTPUT ->
  2528                              <1> 	;	(EAX = 0)
  2529                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2530                              <1> 	;	cf = 0 ->
  2531                              <1> 	;	u.pgdir = page directory (physical) address of the current
  2532                              <1> 	;		  process/user.
  2533                              <1> 	;
  2534                              <1> 	; Modified Registers -> EAX
  2535                              <1> 	;
  2536 00002E1B E896FFFFFF          <1> 	call	allocate_page
  2537 00002E20 7216                <1> 	jc	short mkpd_error
  2538                              <1> 	;
  2539 00002E22 A3[F16E0000]        <1> 	mov	[u.pgdir], eax    ; Page dir address for current user/process
  2540                              <1> 				  ; (Physical address)
  2541                              <1> clear_page:
  2542                              <1> 	; 18/04/2015
  2543                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2544                              <1> 	;
  2545                              <1> 	; INPUT ->
  2546                              <1> 	;	EAX = physical address of the page
  2547                              <1> 	; OUTPUT ->
  2548                              <1> 	;	all bytes of the page will be cleared
  2549                              <1> 	;
  2550                              <1> 	; Modified Registers -> none
  2551                              <1> 	;
  2552 00002E27 57                  <1> 	push	edi
  2553 00002E28 51                  <1> 	push	ecx
  2554 00002E29 50                  <1> 	push	eax
  2555 00002E2A B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  2556 00002E2F 89C7                <1> 	mov	edi, eax
  2557 00002E31 31C0                <1> 	xor	eax, eax
  2558 00002E33 F3AB                <1> 	rep	stosd
  2559 00002E35 58                  <1> 	pop	eax
  2560 00002E36 59                  <1> 	pop	ecx
  2561 00002E37 5F                  <1> 	pop	edi
  2562                              <1> mkpd_error:
  2563                              <1> mkpt_error:
  2564 00002E38 C3                  <1> 	retn
  2565                              <1> 
  2566                              <1> make_page_table:
  2567                              <1> 	; 23/06/2015
  2568                              <1> 	; 18/04/2015
  2569                              <1> 	; 12/04/2015
  2570                              <1> 	; 16/10/2014
  2571                              <1> 	; 09/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2572                              <1> 	;
  2573                              <1> 	; INPUT ->
  2574                              <1> 	;	EBX = virtual (linear) address
  2575                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2576                              <1> 	;	      (higher 20 bits must be ZERO)
  2577                              <1> 	;	      (bit 0 must be 1)	 
  2578                              <1> 	;	u.pgdir = page directory (physical) address
  2579                              <1> 	; OUTPUT ->
  2580                              <1> 	;	EDX = Page directory entry address
  2581                              <1> 	;	EAX = Page table address
  2582                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2583                              <1> 	;	cf = 0 -> page table address in the PDE (EDX)
  2584                              <1> 	;
  2585                              <1> 	; Modified Registers -> EAX, EDX
  2586                              <1> 	;
  2587 00002E39 E878FFFFFF          <1> 	call	allocate_page
  2588 00002E3E 72F8                <1> 	jc	short mkpt_error
  2589 00002E40 E811000000          <1> 	call	set_pde	
  2590 00002E45 EBE0                <1> 	jmp	short clear_page
  2591                              <1> 
  2592                              <1> make_page:
  2593                              <1> 	; 24/07/2015
  2594                              <1> 	; 23/06/2015 ; (Retro UNIX 386 v1 - beginning)
  2595                              <1> 	;
  2596                              <1> 	; INPUT ->
  2597                              <1> 	;	EBX = virtual (linear) address
  2598                              <1> 	;	ECX = page attributes (lower 12 bits)
  2599                              <1> 	;	      (higher 20 bits must be ZERO)
  2600                              <1> 	;	      (bit 0 must be 1)	 
  2601                              <1> 	;	u.pgdir = page directory (physical) address
  2602                              <1> 	; OUTPUT ->
  2603                              <1> 	;	EBX = Virtual address
  2604                              <1> 	;	(EDX = PTE value)
  2605                              <1> 	;	EAX = Physical address
  2606                              <1> 	;	cf = 1 -> insufficient (out of) memory error
  2607                              <1> 	;
  2608                              <1> 	; Modified Registers -> EAX, EDX
  2609                              <1> 	;
  2610 00002E47 E86AFFFFFF          <1> 	call	allocate_page
  2611 00002E4C 7207                <1> 	jc	short mkp_err
  2612 00002E4E E821000000          <1> 	call	set_pte	
  2613 00002E53 73D2                <1> 	jnc	short clear_page ; 18/04/2015
  2614                              <1> mkp_err:
  2615 00002E55 C3                  <1> 	retn
  2616                              <1> 
  2617                              <1> set_pde:	; Set page directory entry (PDE)
  2618                              <1> 	; 20/07/2015
  2619                              <1> 	; 18/04/2015
  2620                              <1> 	; 12/04/2015
  2621                              <1> 	; 23/10/2014
  2622                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2623                              <1> 	;
  2624                              <1> 	; INPUT ->
  2625                              <1> 	;	EAX = physical address
  2626                              <1> 	;	      (use present value if EAX = 0)
  2627                              <1> 	;	EBX = virtual (linear) address
  2628                              <1> 	;	ECX = page table attributes (lower 12 bits)
  2629                              <1> 	;	      (higher 20 bits must be ZERO)
  2630                              <1> 	;	      (bit 0 must be 1)	 
  2631                              <1> 	;	u.pgdir = page directory (physical) address
  2632                              <1> 	; OUTPUT ->
  2633                              <1> 	;	EDX = PDE address
  2634                              <1> 	;	EAX = page table address (physical)
  2635                              <1> 	;	;(CF=1 -> Invalid page address)
  2636                              <1> 	;
  2637                              <1> 	; Modified Registers -> EDX
  2638                              <1> 	;
  2639 00002E56 89DA                <1> 	mov	edx, ebx
  2640 00002E58 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22
  2641 00002E5B C1E202              <1> 	shl	edx, 2 ; offset to page directory (1024*4)
  2642 00002E5E 0315[F16E0000]      <1> 	add	edx, [u.pgdir]
  2643                              <1> 	;
  2644 00002E64 21C0                <1> 	and	eax, eax
  2645 00002E66 7506                <1> 	jnz	short spde_1
  2646                              <1> 	;
  2647 00002E68 8B02                <1> 	mov	eax, [edx]  ; old PDE value
  2648                              <1> 	;test	al, 1
  2649                              <1> 	;jz	short spde_2
  2650 00002E6A 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h  ; clear lower 12 bits
  2651                              <1> spde_1:
  2652                              <1> 	;and	cx, 0FFFh
  2653 00002E6E 8902                <1> 	mov	[edx], eax
  2654 00002E70 66090A              <1> 	or	[edx], cx
  2655 00002E73 C3                  <1> 	retn
  2656                              <1> ;spde_2: ; error
  2657                              <1> ;	stc
  2658                              <1> ;	retn
  2659                              <1> 
  2660                              <1> set_pte:	; Set page table entry (PTE)
  2661                              <1> 	; 24/07/2015
  2662                              <1> 	; 20/07/2015
  2663                              <1> 	; 23/06/2015
  2664                              <1> 	; 18/04/2015
  2665                              <1> 	; 12/04/2015
  2666                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2667                              <1> 	;
  2668                              <1> 	; INPUT ->
  2669                              <1> 	;	EAX = physical page address
  2670                              <1> 	;	      (use present value if EAX = 0)
  2671                              <1> 	;	EBX = virtual (linear) address
  2672                              <1> 	;	ECX = page attributes (lower 12 bits)
  2673                              <1> 	;	      (higher 20 bits must be ZERO)
  2674                              <1> 	;	      (bit 0 must be 1)	 
  2675                              <1> 	;	u.pgdir = page directory (physical) address
  2676                              <1> 	; OUTPUT ->
  2677                              <1> 	;	EAX = physical page address
  2678                              <1> 	;	(EDX = PTE value)
  2679                              <1> 	;	EBX = virtual address
  2680                              <1> 	;
  2681                              <1> 	;	CF = 1 -> error
  2682                              <1> 	;
  2683                              <1> 	; Modified Registers -> EAX, EDX
  2684                              <1> 	;
  2685 00002E74 50                  <1> 	push	eax
  2686 00002E75 A1[F16E0000]        <1> 	mov	eax, [u.pgdir] ; 20/07/2015
  2687 00002E7A E837000000          <1> 	call 	get_pde
  2688                              <1> 		; EDX = PDE address
  2689                              <1> 		; EAX = PDE value
  2690 00002E7F 5A                  <1> 	pop	edx ; physical page address
  2691 00002E80 722A                <1> 	jc	short spte_err ; PDE not present
  2692                              <1> 	;
  2693 00002E82 53                  <1> 	push	ebx ; 24/07/2015
  2694 00002E83 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2695                              <1> 			    ; EDX = PT address (physical)	
  2696 00002E87 C1EB0C              <1> 	shr	ebx, PAGE_SHIFT ; 12
  2697 00002E8A 81E3FF030000        <1> 	and	ebx, PTE_MASK	; 03FFh
  2698                              <1> 			 ; clear higher 10 bits (PD bits)
  2699 00002E90 C1E302              <1> 	shl	ebx, 2   ; offset to page table (1024*4)
  2700 00002E93 01C3                <1> 	add	ebx, eax
  2701                              <1> 	;
  2702 00002E95 8B03                <1> 	mov	eax, [ebx] ; Old PTE value
  2703 00002E97 A801                <1> 	test	al, 1
  2704 00002E99 740C                <1> 	jz	short spte_0
  2705 00002E9B 09D2                <1> 	or	edx, edx
  2706 00002E9D 750F                <1> 	jnz	short spte_1
  2707 00002E9F 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2708 00002EA3 89C2                <1> 	mov	edx, eax
  2709 00002EA5 EB09                <1> 	jmp	short spte_2	
  2710                              <1> spte_0:
  2711                              <1> 	; If this PTE contains a swap (disk) address,
  2712                              <1> 	; it can be updated by using 'swap_in' procedure
  2713                              <1> 	; only!
  2714 00002EA7 21C0                <1> 	and	eax, eax
  2715 00002EA9 7403                <1> 	jz	short spte_1
  2716                              <1> 	; 24/07/2015
  2717                              <1> 	; swapped page ! (on disk)
  2718 00002EAB 5B                  <1> 	pop	ebx
  2719                              <1> spte_err:
  2720 00002EAC F9                  <1> 	stc
  2721 00002EAD C3                  <1> 	retn
  2722                              <1> spte_1: 
  2723 00002EAE 89D0                <1> 	mov	eax, edx
  2724                              <1> spte_2:
  2725 00002EB0 09CA                <1> 	or	edx, ecx
  2726                              <1> 	; 23/06/2015
  2727 00002EB2 8913                <1> 	mov	[ebx], edx ; PTE value in EDX
  2728                              <1> 	; 24/07/2015
  2729 00002EB4 5B                  <1> 	pop	ebx
  2730 00002EB5 C3                  <1> 	retn
  2731                              <1> 
  2732                              <1> get_pde:	; Get present value of the relevant PDE
  2733                              <1> 	; 20/07/2015
  2734                              <1> 	; 18/04/2015
  2735                              <1> 	; 12/04/2015
  2736                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2737                              <1> 	;
  2738                              <1> 	; INPUT ->
  2739                              <1> 	;	EBX = virtual (linear) address
  2740                              <1> 	;	EAX = page directory (physical) address
  2741                              <1> 	; OUTPUT ->
  2742                              <1> 	;	EDX = Page directory entry address
  2743                              <1> 	;	EAX = Page directory entry value
  2744                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2745                              <1> 	; Modified Registers -> EDX, EAX
  2746                              <1> 	;
  2747 00002EB6 89DA                <1> 	mov	edx, ebx
  2748 00002EB8 C1EA16              <1> 	shr	edx, PAGE_D_SHIFT ; 22  (12+10)
  2749 00002EBB C1E202              <1> 	shl 	edx, 2 ; offset to page directory (1024*4)
  2750 00002EBE 01C2                <1> 	add	edx, eax ; page directory address (physical)
  2751 00002EC0 8B02                <1> 	mov	eax, [edx]
  2752 00002EC2 A801                <1> 	test	al, PDE_A_PRESENT ; page table is present or not !
  2753 00002EC4 751F                <1> 	jnz	short gpte_retn
  2754 00002EC6 F9                  <1> 	stc
  2755                              <1> gpde_retn:	
  2756 00002EC7 C3                  <1> 	retn
  2757                              <1> 
  2758                              <1> get_pte:
  2759                              <1> 		; Get present value of the relevant PTE
  2760                              <1> 	; 29/07/2015
  2761                              <1> 	; 20/07/2015
  2762                              <1> 	; 18/04/2015
  2763                              <1> 	; 12/04/2015
  2764                              <1> 	; 10/10/2014 ; (Retro UNIX 386 v1 - beginning)
  2765                              <1> 	;
  2766                              <1> 	; INPUT ->
  2767                              <1> 	;	EBX = virtual (linear) address
  2768                              <1> 	;	EAX = page directory (physical) address
  2769                              <1> 	; OUTPUT ->
  2770                              <1> 	;	EDX = Page table entry address (if CF=0)
  2771                              <1> 	;	      Page directory entry address (if CF=1)
  2772                              <1> 	;            (Bit 0 value is 0 if PT is not present)
  2773                              <1> 	;	EAX = Page table entry value (page address)
  2774                              <1> 	;	CF = 1 -> PDE not present or invalid ? 
  2775                              <1> 	; Modified Registers -> EAX, EDX
  2776                              <1> 	;
  2777 00002EC8 E8E9FFFFFF          <1> 	call 	get_pde
  2778 00002ECD 72F8                <1> 	jc	short gpde_retn	; page table is not present
  2779                              <1> 	;jnc	short gpte_1
  2780                              <1> 	;retn
  2781                              <1> ;gpte_1:
  2782 00002ECF 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 bits
  2783 00002ED3 89DA                <1> 	mov	edx, ebx
  2784 00002ED5 C1EA0C              <1> 	shr	edx, PAGE_SHIFT ; 12
  2785 00002ED8 81E2FF030000        <1> 	and	edx, PTE_MASK	; 03FFh
  2786                              <1> 			 ; clear higher 10 bits (PD bits)
  2787 00002EDE C1E202              <1> 	shl	edx, 2 ; offset from start of page table (1024*4)
  2788 00002EE1 01C2                <1> 	add	edx, eax
  2789 00002EE3 8B02                <1> 	mov	eax, [edx]
  2790                              <1> gpte_retn:
  2791 00002EE5 C3                  <1> 	retn
  2792                              <1> 
  2793                              <1> deallocate_page_dir:
  2794                              <1> 	; 15/09/2015
  2795                              <1> 	; 05/08/2015
  2796                              <1> 	; 30/04/2015
  2797                              <1> 	; 28/04/2015
  2798                              <1> 	; 17/10/2014
  2799                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2800                              <1> 	;
  2801                              <1> 	; INPUT ->
  2802                              <1> 	;	EAX = PHYSICAL ADDRESS OF THE PAGE DIRECTORY (CHILD)
  2803                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2804                              <1> 	; OUTPUT ->
  2805                              <1> 	;	All of page tables in the page directory
  2806                              <1> 	;	and page dir's itself will be deallocated
  2807                              <1> 	;	except 'read only' duplicated pages (will be converted
  2808                              <1> 	;	to writable pages).
  2809                              <1> 	;
  2810                              <1> 	; Modified Registers -> EAX
  2811                              <1> 	;
  2812                              <1> 	;
  2813 00002EE6 56                  <1> 	push	esi
  2814 00002EE7 51                  <1> 	push	ecx
  2815 00002EE8 50                  <1> 	push	eax
  2816 00002EE9 89C6                <1> 	mov	esi, eax 
  2817 00002EEB 31C9                <1> 	xor	ecx, ecx
  2818                              <1> 	; The 1st PDE points to Kernel Page Table 0 (the 1st 4MB),
  2819                              <1> 	; it must not be deallocated
  2820 00002EED 890E                <1> 	mov	[esi], ecx ; 0 ; clear PDE 0
  2821                              <1> dapd_0:
  2822 00002EEF AD                  <1> 	lodsd
  2823 00002EF0 A801                <1> 	test	al, PDE_A_PRESENT ; bit 0, present flag (must be 1)
  2824 00002EF2 7409                <1> 	jz	short dapd_1	
  2825 00002EF4 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2826 00002EF8 E812000000          <1> 	call	deallocate_page_table			
  2827                              <1> dapd_1:
  2828 00002EFD 41                  <1> 	inc	ecx ; page directory entry index
  2829 00002EFE 81F900040000        <1> 	cmp	ecx, PAGE_SIZE / 4 ; 1024
  2830 00002F04 72E9                <1> 	jb	short dapd_0
  2831                              <1> dapd_2:
  2832 00002F06 58                  <1> 	pop	eax
  2833 00002F07 E872000000          <1> 	call	deallocate_page	; deallocate the page dir's itself
  2834 00002F0C 59                  <1> 	pop	ecx
  2835 00002F0D 5E                  <1> 	pop	esi
  2836 00002F0E C3                  <1> 	retn
  2837                              <1> 
  2838                              <1> deallocate_page_table:
  2839                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2840                              <1> 	; 12/07/2016 (TRDOS 386 v2)
  2841                              <1> 	; 19/09/2015
  2842                              <1> 	; 15/09/2015
  2843                              <1> 	; 05/08/2015
  2844                              <1> 	; 30/04/2015
  2845                              <1> 	; 28/04/2015
  2846                              <1> 	; 24/10/2014
  2847                              <1> 	; 23/10/2014
  2848                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2849                              <1> 	;
  2850                              <1> 	; INPUT ->
  2851                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE PAGE TABLE
  2852                              <1> 	;	EBX = PHYSICAL ADDRESS OF THE PARENT'S PAGE DIRECTORY
  2853                              <1> 	;	(ECX = page directory entry index)
  2854                              <1> 	; OUTPUT ->
  2855                              <1> 	;	All of pages in the page table and page table's itself
  2856                              <1> 	;	will be deallocated except 'read only' duplicated pages
  2857                              <1> 	;	(will be converted to writable pages).
  2858                              <1> 	;
  2859                              <1> 	; Modified Registers -> EAX
  2860                              <1> 	;
  2861 00002F0F 56                  <1> 	push	esi
  2862 00002F10 57                  <1> 	push	edi
  2863 00002F11 52                  <1> 	push	edx
  2864 00002F12 50                  <1> 	push	eax ; *
  2865 00002F13 89C6                <1> 	mov	esi, eax 
  2866 00002F15 31FF                <1> 	xor	edi, edi ; 0
  2867                              <1> dapt_0:
  2868 00002F17 AD                  <1> 	lodsd
  2869 00002F18 A801                <1> 	test	al, PTE_A_PRESENT ; bit 0, present flag (must be 1)
  2870 00002F1A 7455                <1> 	jz	short dapt_1
  2871                              <1> 	;
  2872 00002F1C A802                <1> 	test	al, PTE_A_WRITE   ; bit 1, writable (r/w) flag
  2873                              <1> 				  ; (must be 1)
  2874 00002F1E 753F                <1> 	jnz	short dapt_3
  2875                              <1> 	; Read only -duplicated- page (belongs to a parent or a child)
  2876 00002F20 66A90002            <1>         test    ax, PTE_DUPLICATED ; Was this page duplicated 
  2877                              <1> 				   ; as child's page ?
  2878 00002F24 7444                <1> 	jz	short dapt_4 ; Clear PTE but don't deallocate the page!
  2879                              <1> 	; check the parent's PTE value is read only & same page or not.. 
  2880                              <1> 	; ECX = page directory entry index (0-1023)
  2881 00002F26 53                  <1> 	push	ebx
  2882 00002F27 51                  <1> 	push	ecx
  2883 00002F28 66C1E102            <1> 	shl	cx, 2 ; *4 
  2884 00002F2C 01CB                <1> 	add	ebx, ecx ; PDE offset (for the parent)
  2885 00002F2E 8B0B                <1> 	mov	ecx, [ebx]
  2886 00002F30 F6C101              <1> 	test	cl, PDE_A_PRESENT ; present (valid) or not ?
  2887 00002F33 7428                <1> 	jz	short dapt_2	; parent process does not use this page
  2888 00002F35 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  2889                              <1> 	; EDI = page table entry index (0-1023)
  2890 00002F3A 89FA                <1> 	mov	edx, edi 
  2891 00002F3C 66C1E202            <1> 	shl	dx, 2 ; *4 
  2892 00002F40 01CA                <1> 	add	edx, ecx ; PTE offset (for the parent)
  2893 00002F42 8B1A                <1> 	mov	ebx, [edx]
  2894 00002F44 F6C301              <1> 	test	bl, PTE_A_PRESENT ; present or not ?
  2895 00002F47 7414                <1> 	jz	short dapt_2	; parent process does not use this page
  2896 00002F49 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; Clear attribute bits 
  2897 00002F4D 6681E300F0          <1> 	and	bx, PTE_A_CLEAR ; 0F000h ; Clear attribute bits
  2898 00002F52 39D8                <1> 	cmp	eax, ebx	; parent's and child's pages are same ?
  2899 00002F54 7507                <1> 	jne	short dapt_2	; not same page
  2900                              <1> 				; deallocate the child's page
  2901 00002F56 800A02              <1>         or      byte [edx], PTE_A_WRITE ; convert to writable page (parent)
  2902 00002F59 59                  <1> 	pop	ecx
  2903 00002F5A 5B                  <1> 	pop	ebx
  2904 00002F5B EB0D                <1> 	jmp	short dapt_4
  2905                              <1> 
  2906                              <1> ; 24/12/2021
  2907                              <1> ; ('dapt_1' is disabled)
  2908                              <1> ;
  2909                              <1> ;dapt_1:
  2910                              <1> ;	or	eax, eax	; swapped page ?
  2911                              <1> ;	jz	short dapt_5	; no
  2912                              <1> ;				; yes
  2913                              <1> ;	shr	eax, 1
  2914                              <1> ;	call	unlink_swap_block ; Deallocate swapped page block
  2915                              <1> ;				  ; on the swap disk (or in file)
  2916                              <1> ;	jmp	short dapt_5
  2917                              <1> dapt_2:
  2918 00002F5D 59                  <1> 	pop	ecx
  2919 00002F5E 5B                  <1> 	pop	ebx
  2920                              <1> dapt_3:	
  2921                              <1> 	; 12/07/2016
  2922 00002F5F 66A90004            <1> 	test	ax, PTE_SHARED ; shared or direct memory access indicator
  2923 00002F63 7505                <1> 	jnz	short dapt_4   ; AVL bit 1 = 1, do not deallocate this page!
  2924                              <1> 	;
  2925                              <1> 	;and	ax, PTE_A_CLEAR ; 0F000h ; clear lower 12 (attribute) bits
  2926 00002F65 E814000000          <1> 	call	deallocate_page ; set the mem allocation bit of this page
  2927                              <1> dapt_4:
  2928 00002F6A C746FC00000000      <1> 	mov	dword [esi-4], 0 ; clear/reset PTE (child, dupl. as parent)
  2929                              <1> dapt_1:	; 24/12/2021
  2930                              <1> dapt_5:
  2931 00002F71 47                  <1> 	inc	edi ; page table entry index
  2932 00002F72 81FF00040000        <1> 	cmp	edi, PAGE_SIZE / 4 ; 1024
  2933 00002F78 729D                <1> 	jb	short dapt_0
  2934                              <1> 	;
  2935 00002F7A 58                  <1> 	pop	eax ; *
  2936 00002F7B 5A                  <1> 	pop	edx
  2937 00002F7C 5F                  <1> 	pop	edi	
  2938 00002F7D 5E                  <1> 	pop	esi
  2939                              <1> 	;
  2940                              <1> 	;call	deallocate_page	; deallocate the page table's itself
  2941                              <1> 	;retn
  2942                              <1> 
  2943                              <1> deallocate_page:
  2944                              <1> 	; 15/09/2015
  2945                              <1> 	; 28/04/2015
  2946                              <1> 	; 10/03/2015
  2947                              <1> 	; 17/10/2014
  2948                              <1> 	; 12/10/2014 (Retro UNIX 386 v1 - beginning)
  2949                              <1> 	;
  2950                              <1> 	; INPUT -> 
  2951                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  2952                              <1> 	; OUTPUT ->
  2953                              <1> 	;	[free_pages] is increased
  2954                              <1> 	;	(corresponding MEMORY ALLOCATION TABLE bit is SET)
  2955                              <1> 	;	CF = 1 if the page is already deallocated
  2956                              <1> 	; 	       (or not allocated) before.  
  2957                              <1> 	;
  2958                              <1> 	; Modified Registers -> EAX
  2959                              <1> 	;
  2960 00002F7E 53                  <1> 	push	ebx
  2961 00002F7F 52                  <1> 	push	edx
  2962                              <1> 	;
  2963 00002F80 C1E80C              <1> 	shr	eax, PAGE_SHIFT      ; shift physical address to 
  2964                              <1> 				     ; 12 bits right
  2965                              <1> 				     ; to get page number
  2966 00002F83 89C2                <1> 	mov	edx, eax
  2967                              <1> 	; 15/09/2015
  2968 00002F85 C1EA03              <1> 	shr	edx, 3		     ; to get offset to M.A.T.
  2969                              <1> 				     ; (1 allocation bit = 1 page)
  2970                              <1> 				     ; (1 allocation bytes = 8 pages)
  2971 00002F88 80E2FC              <1> 	and	dl, 0FCh 	     ; clear lower 2 bits
  2972                              <1> 				     ; (to get 32 bit position)			
  2973                              <1> 	;
  2974 00002F8B BB00001000          <1> 	mov	ebx, MEM_ALLOC_TBL   ; Memory Allocation Table address
  2975 00002F90 01D3                <1> 	add	ebx, edx
  2976 00002F92 83E01F              <1> 	and	eax, 1Fh	     ; lower 5 bits only
  2977                              <1> 				     ; (allocation bit position)	 
  2978 00002F95 3B15[E46A0000]      <1> 	cmp 	edx, [next_page]     ; is the new free page address lower
  2979                              <1> 				     ; than the address in 'next_page' ?
  2980                              <1> 				     ; (next/first free page value)		
  2981 00002F9B 7306                <1> 	jnb	short dap_1	     ; no	
  2982 00002F9D 8915[E46A0000]      <1> 	mov	[next_page], edx     ; yes
  2983                              <1> dap_1:
  2984 00002FA3 0FAB03              <1> 	bts	[ebx], eax	     ; unlink/release/deallocate page
  2985                              <1> 				     ; set relevant bit to 1.
  2986                              <1> 				     ; set CF to the previous bit value	
  2987                              <1> 	;cmc			     ; complement carry flag	
  2988                              <1> 	;jc	short dap_2	     ; do not increase free_pages count
  2989                              <1> 				     ; if the page is already deallocated
  2990                              <1> 				     ; before.	
  2991 00002FA6 FF05[E06A0000]      <1>         inc     dword [free_pages]
  2992                              <1> dap_2:
  2993 00002FAC 5A                  <1> 	pop	edx
  2994 00002FAD 5B                  <1> 	pop	ebx
  2995 00002FAE C3                  <1> 	retn
  2996                              <1> 
  2997                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2998                              <1> ;;                                                              ;;
  2999                              <1> ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  3000                              <1> ;; Distributed under terms of the GNU General Public License    ;;
  3001                              <1> ;;                                                              ;;
  3002                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  3003                              <1> 
  3004                              <1> ;;$Revision: 5057 $
  3005                              <1> 
  3006                              <1> 
  3007                              <1> ;;align 4
  3008                              <1> ;;proc alloc_page
  3009                              <1> 
  3010                              <1> ;;        pushfd
  3011                              <1> ;;        cli
  3012                              <1> ;;        push    ebx
  3013                              <1> ;;;//-
  3014                              <1> ;;        cmp     [pg_data.pages_free], 1
  3015                              <1> ;;        jle     .out_of_memory
  3016                              <1> ;;;//-
  3017                              <1> ;;
  3018                              <1> ;;        mov     ebx, [page_start]
  3019                              <1> ;;        mov     ecx, [page_end]
  3020                              <1> ;;.l1:
  3021                              <1> ;;        bsf     eax, [ebx];
  3022                              <1> ;;        jnz     .found
  3023                              <1> ;;        add     ebx, 4
  3024                              <1> ;;        cmp     ebx, ecx
  3025                              <1> ;;        jb      .l1
  3026                              <1> ;;        pop     ebx
  3027                              <1> ;;        popfd
  3028                              <1> ;;        xor     eax, eax
  3029                              <1> ;;        ret
  3030                              <1> ;;.found:
  3031                              <1> ;;;//-
  3032                              <1> ;;        dec     [pg_data.pages_free]
  3033                              <1> ;;        jz      .out_of_memory
  3034                              <1> ;;;//-
  3035                              <1> ;;        btr     [ebx], eax
  3036                              <1> ;;        mov     [page_start], ebx
  3037                              <1> ;;        sub     ebx, sys_pgmap
  3038                              <1> ;;        lea     eax, [eax+ebx*8]
  3039                              <1> ;;        shl     eax, 12
  3040                              <1> ;;;//-       dec [pg_data.pages_free]
  3041                              <1> ;;        pop     ebx
  3042                              <1> ;;        popfd
  3043                              <1> ;;        ret
  3044                              <1> ;;;//-
  3045                              <1> ;;.out_of_memory:
  3046                              <1> ;;        mov     [pg_data.pages_free], 1
  3047                              <1> ;;        xor     eax, eax
  3048                              <1> ;;        pop     ebx
  3049                              <1> ;;        popfd
  3050                              <1> ;;        ret
  3051                              <1> ;;;//-
  3052                              <1> ;;endp
  3053                              <1> 
  3054                              <1> duplicate_page_dir:
  3055                              <1> 	; 21/09/2015
  3056                              <1> 	; 31/08/2015
  3057                              <1> 	; 20/07/2015
  3058                              <1> 	; 28/04/2015
  3059                              <1> 	; 27/04/2015
  3060                              <1> 	; 18/04/2015
  3061                              <1> 	; 12/04/2015
  3062                              <1> 	; 18/10/2014
  3063                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3064                              <1> 	;
  3065                              <1> 	; INPUT -> 
  3066                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  3067                              <1> 	;		    page directory.
  3068                              <1> 	; OUTPUT ->
  3069                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  3070                              <1> 	;	       page directory.
  3071                              <1> 	;	(New page directory with new page table entries.)
  3072                              <1> 	;	(New page tables with read only copies of the parent's
  3073                              <1> 	;	pages.)
  3074                              <1> 	;	EAX = 0 -> Error (CF = 1)
  3075                              <1> 	;
  3076                              <1> 	; Modified Registers -> none (except EAX)
  3077                              <1> 	;
  3078 00002FAF E802FEFFFF          <1> 	call	allocate_page
  3079 00002FB4 723E                <1> 	jc	short dpd_err
  3080                              <1> 	;
  3081 00002FB6 55                  <1> 	push	ebp ; 20/07/2015
  3082 00002FB7 56                  <1> 	push	esi
  3083 00002FB8 57                  <1> 	push	edi
  3084 00002FB9 53                  <1> 	push	ebx
  3085 00002FBA 51                  <1> 	push	ecx
  3086 00002FBB 8B35[F16E0000]      <1> 	mov	esi, [u.pgdir]
  3087 00002FC1 89C7                <1> 	mov	edi, eax
  3088 00002FC3 50                  <1> 	push	eax ; save child's page directory address
  3089                              <1> 	; 31/08/2015
  3090                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  3091                              <1> 	; (use same system space for all user page tables) 
  3092 00002FC4 A5                  <1> 	movsd
  3093 00002FC5 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  3094 00002FCA B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  3095                              <1> dpd_0:	
  3096 00002FCF AD                  <1> 	lodsd
  3097                              <1> 	;or	eax, eax
  3098                              <1>         ;jnz     short dpd_1
  3099 00002FD0 A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  3100 00002FD2 7508                <1> 	jnz	short dpd_1
  3101                              <1>  	; 20/07/2015 (virtual address at the end of the page table)	
  3102 00002FD4 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  3103 00002FDA EB0F                <1> 	jmp	short dpd_2
  3104                              <1> dpd_1:	
  3105 00002FDC 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  3106 00002FE0 89C3                <1> 	mov	ebx, eax
  3107                              <1> 	; EBX = Parent's page table address
  3108 00002FE2 E81F000000          <1> 	call	duplicate_page_table
  3109 00002FE7 720C                <1> 	jc	short dpd_p_err
  3110                              <1> 	; EAX = Child's page table address
  3111 00002FE9 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  3112                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  3113                              <1> 			 ; (present, writable, user)
  3114                              <1> dpd_2:
  3115 00002FEB AB                  <1> 	stosd
  3116 00002FEC E2E1                <1> 	loop	dpd_0
  3117                              <1> 	;
  3118 00002FEE 58                  <1> 	pop	eax  ; restore child's page directory address
  3119                              <1> dpd_3:
  3120 00002FEF 59                  <1> 	pop	ecx
  3121 00002FF0 5B                  <1> 	pop	ebx
  3122 00002FF1 5F                  <1> 	pop	edi
  3123 00002FF2 5E                  <1> 	pop	esi
  3124 00002FF3 5D                  <1> 	pop	ebp ; 20/07/2015
  3125                              <1> dpd_err:
  3126 00002FF4 C3                  <1> 	retn
  3127                              <1> dpd_p_err:
  3128                              <1> 	; release the allocated pages missing (recover free space)
  3129 00002FF5 58                  <1> 	pop	eax  ; the new page directory address (physical)
  3130 00002FF6 8B1D[F16E0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  3131 00002FFC E8E5FEFFFF          <1> 	call 	deallocate_page_dir
  3132 00003001 29C0                <1> 	sub	eax, eax ; 0
  3133 00003003 F9                  <1> 	stc
  3134 00003004 EBE9                <1> 	jmp	short dpd_3	
  3135                              <1> 
  3136                              <1> duplicate_page_table:
  3137                              <1> 	; 31/12/2021
  3138                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3139                              <1> 	; 20/02/2017 (TRDOS 386 v2)
  3140                              <1> 	; 21/09/2015
  3141                              <1> 	; 20/07/2015
  3142                              <1> 	; 05/05/2015
  3143                              <1> 	; 28/04/2015
  3144                              <1> 	; 27/04/2015
  3145                              <1> 	; 18/04/2015
  3146                              <1> 	; 18/10/2014
  3147                              <1> 	; 16/10/2014 (Retro UNIX 386 v1 - beginning)
  3148                              <1> 	;
  3149                              <1> 	; INPUT -> 
  3150                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  3151                              <1> 	;       20/02/2017		 
  3152                              <1> 	;	EBP = Linear address of the page (from 'duplicate_page_dir')
  3153                              <1> 	;	      (Linear address = CORE + user's virtual address) 	
  3154                              <1> 	; OUTPUT ->
  3155                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  3156                              <1> 	;	      (with 'read only' attribute of page table entries)
  3157                              <1> 	;	20/02/2017
  3158                              <1> 	;	EBP = Next linear page address (for 'duplicate_page_dir')
  3159                              <1> 	;	
  3160                              <1> 	;	CF = 1 -> error 
  3161                              <1> 	;
  3162                              <1> 	; Modified Registers -> EBP (except EAX)
  3163                              <1> 	;
  3164 00003006 E8ABFDFFFF          <1> 	call	allocate_page
  3165 0000300B 725B                <1> 	jc	short dpt_err
  3166                              <1> 	;
  3167 0000300D 50                  <1> 	push	eax ; *
  3168 0000300E 56                  <1> 	push	esi
  3169 0000300F 57                  <1> 	push	edi
  3170 00003010 52                  <1> 	push	edx
  3171 00003011 51                  <1> 	push	ecx
  3172                              <1> 	;
  3173 00003012 89DE                <1> 	mov	esi, ebx
  3174 00003014 89C7                <1> 	mov	edi, eax
  3175 00003016 89C2                <1> 	mov	edx, eax
  3176 00003018 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  3177                              <1> dpt_0:
  3178 0000301E AD                  <1> 	lodsd
  3179 0000301F 21C0                <1> 	and	eax, eax
  3180 00003021 7435                <1> 	jz	short dpt_3
  3181 00003023 A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 =  1
  3182                              <1> 	; 24/12/2021
  3183 00003025 7503                <1> 	jnz	short dpt_1
  3184                              <1> 	;jz	short dpt_p_err
  3185                              <1> 	; 31/12/2021
  3186 00003027 F9                  <1> 	stc
  3187 00003028 EB39                <1> 	jmp	short dpt_p_err
  3188                              <1> 
  3189                              <1> ; 24/12/2021
  3190                              <1> ; ('reload_page' procedure call is disabled)
  3191                              <1> ;
  3192                              <1> ;	; 20/07/2015
  3193                              <1> ;	; ebp = virtual (linear) address of the memory page
  3194                              <1> ;	call	reload_page ; 28/04/2015
  3195                              <1> ;	jc	short dpt_p_err
  3196                              <1> dpt_1:
  3197                              <1> 	; 21/09/2015
  3198 0000302A 89C1                <1> 	mov	ecx, eax
  3199 0000302C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3200 00003030 F6C102              <1> 	test	cl, PTE_A_WRITE ; writable page ?
  3201 00003033 751A                <1> 	jnz	short dpt_2
  3202                              <1> 	; Read only (parent) page
  3203                              <1> 	; 	- there is a third process which uses this page -
  3204                              <1> 	; Allocate a new page for the child process
  3205 00003035 E87CFDFFFF          <1> 	call	allocate_page
  3206 0000303A 7227                <1> 	jc	short dpt_p_err
  3207 0000303C 57                  <1> 	push	edi
  3208 0000303D 56                  <1> 	push	esi
  3209 0000303E 89CE                <1> 	mov	esi, ecx
  3210 00003040 89C7                <1> 	mov	edi, eax
  3211 00003042 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  3212 00003047 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  3213 00003049 5E                  <1> 	pop	esi
  3214 0000304A 5F                  <1> 	pop	edi
  3215                              <1> 	;
  3216                              <1> 
  3217                              <1> ; 24/12/2021
  3218                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  3219                              <1> ; 
  3220                              <1> ;	push	ebx
  3221                              <1> ;	push	eax
  3222                              <1> ;	; 20/07/2015
  3223                              <1> ;	mov	ebx, ebp
  3224                              <1> ;	; ebx = virtual (linear) address of the memory page
  3225                              <1> ;	call	add_to_swap_queue
  3226                              <1> ;	pop	eax
  3227                              <1> ;	pop	ebx
  3228                              <1> 
  3229                              <1> 	; 21/09/2015
  3230 0000304B 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  3231                              <1> 		; user + writable + present page
  3232 0000304D EB09                <1> 	jmp	short dpt_3
  3233                              <1> dpt_2:
  3234                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  3235 0000304F 0C05                <1> 	or	al, PTE_A_USER+PTE_A_PRESENT 
  3236                              <1> 		    ; (read only page!)
  3237 00003051 8946FC              <1> 	mov	[esi-4], eax ; update parent's PTE
  3238 00003054 660D0002            <1> 	or      ax, PTE_DUPLICATED  ; (read only page & duplicated PTE!)
  3239                              <1> dpt_3:
  3240 00003058 AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  3241                              <1> 	;
  3242 00003059 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  3243                              <1> 	;
  3244 0000305F 39D7                <1> 	cmp	edi, edx
  3245 00003061 72BB                <1> 	jb	short dpt_0
  3246                              <1> dpt_p_err:
  3247 00003063 59                  <1> 	pop	ecx
  3248 00003064 5A                  <1> 	pop	edx
  3249 00003065 5F                  <1> 	pop	edi
  3250 00003066 5E                  <1> 	pop	esi
  3251 00003067 58                  <1> 	pop	eax ; *
  3252                              <1> dpt_err:
  3253 00003068 C3                  <1> 	retn
  3254                              <1> 
  3255                              <1> page_fault_handler: ; CPU EXCEPTION 0Eh (14) : Page Fault !
  3256                              <1> 	; 31/12/2021
  3257                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3258                              <1> 	; 21/09/2015
  3259                              <1> 	; 19/09/2015
  3260                              <1> 	; 17/09/2015
  3261                              <1> 	; 28/08/2015
  3262                              <1> 	; 20/07/2015
  3263                              <1> 	; 28/06/2015
  3264                              <1> 	; 03/05/2015
  3265                              <1> 	; 30/04/2015
  3266                              <1> 	; 18/04/2015
  3267                              <1> 	; 12/04/2015
  3268                              <1> 	; 30/10/2014
  3269                              <1> 	; 11/09/2014
  3270                              <1> 	; 10/09/2014 (Retro UNIX 386 v1 - beginning)
  3271                              <1> 	;
  3272                              <1> 	; Note: This is not an interrupt/exception handler.
  3273                              <1> 	;	This is a 'page fault remedy' subroutine 
  3274                              <1> 	;	which will be called by standard/uniform
  3275                              <1> 	;	exception handler.
  3276                              <1> 	;
  3277                              <1> 	; INPUT -> 
  3278                              <1> 	;	[error_code] = 32 bit ERROR CODE (lower 5 bits are valid)
  3279                              <1> 	;
  3280                              <1> 	;	cr2 = the virtual (linear) address 
  3281                              <1> 	;	      which has caused to page fault (19/09/2015)
  3282                              <1> 	;
  3283                              <1> 	; OUTPUT ->
  3284                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3285                              <1> 	;	EAX = 0 -> no error
  3286                              <1> 	;	EAX > 0 -> error code in EAX (also CF = 1)
  3287                              <1> 	;
  3288                              <1> 	; Modified Registers -> none (except EAX)
  3289                              <1> 	;	
  3290                              <1>         ;
  3291                              <1>         ; ERROR CODE:
  3292                              <1> 	;	 31  .....	4   3	2   1	0
  3293                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3294                              <1> 	;	|   Reserved  | I | R | U | W | P |
  3295                              <1> 	;	+---+-- --+---+---+---+---+---+---+
  3296                              <1> 	;
  3297                              <1> 	; P : PRESENT -	When set, the page fault was caused by 
  3298                              <1>     	;		a page-protection violation. When not set,
  3299                              <1> 	;		it was caused by a non-present page.
  3300                              <1> 	; W : WRITE   -	When set, the page fault was caused by
  3301                              <1> 	;		a page write. When not set, it was caused
  3302                              <1> 	;		by a page read.
  3303                              <1> 	; U : USER    -	When set, the page fault was caused 
  3304                              <1> 	;		while CPL = 3. 
  3305                              <1> 	;		This does not necessarily mean that
  3306                              <1> 	;		the page fault was a privilege violation.
  3307                              <1> 	; R : RESERVD -	When set, the page fault was caused by
  3308                              <1> 	;     WRITE	reading a 1 in a reserved field.
  3309                              <1> 	; I : INSTRUC -	When set, the page fault was caused by
  3310                              <1> 	;     FETCH	an instruction fetch
  3311                              <1> 	;
  3312                              <1> 	;; x86 (32 bit) VIRTUAL ADDRESS TRANSLATION
  3313                              <1> 	;  31               22                  12 11                    0
  3314                              <1> 	; +-------------------+-------------------+-----------------------+
  3315                              <1>        	; | PAGE DIR. ENTRY # | PAGE TAB. ENTRY # |        OFFSET         |
  3316                              <1>        	; +-------------------+-------------------+-----------------------+
  3317                              <1> 	;
  3318                              <1> 
  3319                              <1> 	;; CR3 REGISTER (Control Register 3)
  3320                              <1> 	;  31                                   12             5 4 3 2   0
  3321                              <1> 	; +---------------------------------------+-------------+---+-----+
  3322                              <1>       	; |                                       |  		|P|P|     |
  3323                              <1>       	; |   PAGE DIRECTORY TABLE BASE ADDRESS   |  reserved	|C|W|rsvrd|
  3324                              <1>       	; |                                       | 		|D|T|     |
  3325                              <1>    	; +---------------------------------------+-------------+---+-----+
  3326                              <1> 	;
  3327                              <1> 	;	PWT    - WRITE THROUGH
  3328                              <1> 	;	PCD    - CACHE DISABLE		
  3329                              <1> 	;
  3330                              <1> 	;
  3331                              <1> 	;; x86 PAGE DIRECTORY ENTRY (4 KByte Page)
  3332                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3333                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3334                              <1>       	; |                                       |     | | | | |P|P|U|R| |
  3335                              <1>       	; |     PAGE TABLE BASE ADDRESS 31..12    | AVL |G|0|D|A|C|W|/|/|P|
  3336                              <1>       	; |                                       |     | | | | |D|T|S|W| |
  3337                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3338                              <1> 	;
  3339                              <1>         ;       P      - PRESENT
  3340                              <1>         ;       R/W    - READ/WRITE
  3341                              <1>         ;       U/S    - USER/SUPERVISOR
  3342                              <1> 	;	PWT    - WRITE THROUGH
  3343                              <1> 	;	PCD    - CACHE DISABLE	
  3344                              <1> 	;	A      - ACCESSED	
  3345                              <1>         ;       D      - DIRTY (IGNORED)
  3346                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3347                              <1> 	;	G      - GLOBAL	(IGNORED) 
  3348                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3349                              <1> 	;
  3350                              <1> 	;
  3351                              <1> 	;; x86 PAGE TABLE ENTRY (4 KByte Page)
  3352                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3353                              <1> 	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3354                              <1>       	; |                                       |     | |P| | |P|P|U|R| |
  3355                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |G|A|D|A|C|W|/|/|P|
  3356                              <1>       	; |                                       |     | |T| | |D|T|S|W| |
  3357                              <1>    	; +---------------------------------------+-----+---+-+-+---+-+-+-+
  3358                              <1> 	;
  3359                              <1>         ;       P      - PRESENT
  3360                              <1>         ;       R/W    - READ/WRITE
  3361                              <1>         ;       U/S    - USER/SUPERVISOR
  3362                              <1> 	;	PWT    - WRITE THROUGH
  3363                              <1> 	;	PCD    - CACHE DISABLE	
  3364                              <1> 	;	A      - ACCESSED	
  3365                              <1>         ;       D      - DIRTY
  3366                              <1> 	;	PAT    - PAGE ATTRIBUTE TABLE INDEX (CACHE BEHAVIOR)
  3367                              <1> 	;	G      - GLOBAL	 
  3368                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3369                              <1> 	;
  3370                              <1> 	;
  3371                              <1> 	;; 80386 PAGE TABLE ENTRY (4 KByte Page)
  3372                              <1> 	;  31                                   12 11  9 8 7 6 5 4 3 2 1 0
  3373                              <1> 	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3374                              <1>       	; |                                       |     | | | | | | |U|R| |
  3375                              <1>       	; |     PAGE FRAME BASE ADDRESS 31..12    | AVL |0|0|D|A|0|0|/|/|P|
  3376                              <1>       	; |                                       |     | | | | | | |S|W| |
  3377                              <1>       	; +---------------------------------------+-----+-+-+-+-+---+-+-+-+
  3378                              <1> 	;
  3379                              <1>         ;       P      - PRESENT
  3380                              <1>         ;       R/W    - READ/WRITE
  3381                              <1>         ;       U/S    - USER/SUPERVISOR
  3382                              <1>         ;       D      - DIRTY
  3383                              <1>         ;       AVL    - AVAILABLE FOR SYSTEMS PROGRAMMER USE
  3384                              <1> 	;
  3385                              <1>         ;       NOTE: 0 INDICATES INTEL RESERVED. DO NOT DEFINE.
  3386                              <1> 	;
  3387                              <1> 	;
  3388                              <1> 	;; Invalid Page Table Entry
  3389                              <1> 	; 31                                                           1 0
  3390                              <1>       	; +-------------------------------------------------------------+-+
  3391                              <1>       	; |                                                             | |
  3392                              <1>       	; |                          AVAILABLE                          |0|
  3393                              <1>       	; |                                                             | |
  3394                              <1>       	; +-------------------------------------------------------------+-+
  3395                              <1> 	;
  3396                              <1> 
  3397 00003069 53                  <1> 	push	ebx
  3398 0000306A 52                  <1> 	push	edx
  3399 0000306B 51                  <1> 	push	ecx
  3400                              <1> 	;
  3401                              <1> 	; 21/09/2015 (debugging)
  3402 0000306C FF05[016F0000]      <1> 	inc	dword [u.pfcount] ; page fault count for running process
  3403 00003072 FF05[906B0000]      <1> 	inc	dword [PF_Count]  ; total page fault count	
  3404                              <1> 	; 28/06/2015
  3405                              <1> 	;mov	edx, [error_code] ; Lower 5 bits are valid
  3406 00003078 8A15[886B0000]      <1> 	mov	dl, [error_code]
  3407                              <1> 	;
  3408 0000307E F6C201              <1> 	test	dl, 1	; page fault was caused by a non-present page
  3409                              <1> 			; sign
  3410 00003081 7425                <1> 	jz	short pfh_alloc_np
  3411                              <1> 	; 
  3412                              <1> 	; If it is not a 'write on read only page' type page fault
  3413                              <1> 	; major page fault error with minor reason must be returned without 
  3414                              <1> 	; fixing the problem. 'sys_exit with error' will be needed
  3415                              <1> 	; after return here!
  3416                              <1> 	; Page fault will be remedied, by copying page contents
  3417                              <1> 	; to newly allocated page with write permission;
  3418                              <1> 	; sys_fork -> sys_exec -> copy on write, demand paging method is 
  3419                              <1> 	; used for working with minimum possible memory usage. 
  3420                              <1> 	; sys_fork will duplicate page directory and tables of parent  
  3421                              <1> 	; process with 'read only' flag. If the child process attempts to
  3422                              <1> 	; write on these read only pages, page fault will be directed here
  3423                              <1> 	; for allocating a new page with same data/content. 
  3424                              <1> 	;
  3425                              <1> 	; IMPORTANT : Retro UNIX 386 v1 (and SINGLIX and TR-DOS)
  3426                              <1> 	; will not force to separate CODE and DATA space 
  3427                              <1> 	; in a process/program... 
  3428                              <1> 	; CODE segment/section may contain DATA!
  3429                              <1> 	; It is flat, smoth and simplest programming method already as in 
  3430                              <1> 	; Retro UNIX 8086 v1 and MS-DOS programs.
  3431                              <1> 	;	
  3432 00003083 F6C202              <1> 	test	dl, 2	; page fault was caused by a page write
  3433                              <1> 			; sign
  3434 00003086 7418                <1>         jz      pfh_p_err
  3435                              <1> 	; 31/08/2015
  3436 00003088 F6C204              <1> 	test	dl, 4	; page fault was caused while CPL = 3 (user mode)
  3437                              <1> 			; sign.  (U+W+P = 4+2+1 = 7)
  3438 0000308B 7413                <1>         jz	short pfh_pv_err
  3439                              <1> 	;
  3440                              <1> 	; make a new page and copy the parent's page content
  3441                              <1> 	; as the child's new page content
  3442                              <1> 	;
  3443 0000308D 0F20D3              <1> 	mov	ebx, cr2 ; CR2 contains the linear address 
  3444                              <1> 			 ; which has caused to page fault
  3445 00003090 E87C000000          <1> 	call 	copy_page
  3446 00003095 7202                <1>         jc	short pfh_im_err ; insufficient memory
  3447                              <1> 	;
  3448 00003097 EB72                <1>         jmp     pfh_cpp_ok
  3449                              <1> 
  3450                              <1> 	; 31/12/2021 (short jump)
  3451                              <1> pfh_im_err:
  3452 00003099 B8E4000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_IM ; Error code in AX
  3453                              <1> 			; Major (Primary) Error: Page Fault
  3454                              <1> 			; Minor (Secondary) Error: Insufficient Memory !
  3455 0000309E EB6D                <1> 	jmp	short pfh_err_retn
  3456                              <1> 
  3457                              <1> 	; 31/12/2021
  3458                              <1> pfh_p_err: ; 09/03/2015
  3459                              <1> pfh_pv_err:
  3460                              <1> 	; Page fault was caused by a protection-violation
  3461 000030A0 B8E6000000          <1> 	mov	eax, ERR_MAJOR_PF + ERR_MINOR_PV ; Error code in AX
  3462                              <1> 			; Major (Primary) Error: Page Fault
  3463                              <1> 			; Minor (Secondary) Error: Protection violation !
  3464 000030A5 F9                  <1> 	stc
  3465 000030A6 EB65                <1> 	jmp	short pfh_err_retn
  3466                              <1> 	
  3467                              <1> pfh_alloc_np:
  3468 000030A8 E809FDFFFF          <1> 	call	allocate_page	; (allocate a new page)
  3469 000030AD 72EA                <1>         jc	short pfh_im_err ; 'insufficient memory' error
  3470                              <1> pfh_chk_cpl:
  3471                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3472                              <1> 		; (Lower 12 bits are ZERO, because 
  3473                              <1> 		;	the address is on a page boundary)
  3474 000030AF 80E204              <1> 	and	dl, 4	; CPL = 3 ?
  3475 000030B2 7505                <1> 	jnz	short pfh_um
  3476                              <1> 			; Page fault handler for kernel/system mode (CPL=0)		
  3477 000030B4 0F20DB              <1> 	mov	ebx, cr3 ; CR3 (Control Register 3) contains physical address
  3478                              <1> 			 ; of the current/active page directory
  3479                              <1> 			 ; (Always kernel/system mode page directory, here!)
  3480                              <1> 			 ; Note: Lower 12 bits are 0. (page boundary)
  3481 000030B7 EB06                <1> 	jmp	short pfh_get_pde
  3482                              <1> 	;
  3483                              <1> pfh_um:			; Page fault handler for user/appl. mode (CPL=3)
  3484 000030B9 8B1D[F16E0000]      <1>  	mov	ebx, [u.pgdir] ; Page directory of current/active process
  3485                              <1> 			; Physical address of the USER's page directory
  3486                              <1> 			; Note: Lower 12 bits are 0. (page boundary)
  3487                              <1> pfh_get_pde:
  3488 000030BF 80CA03              <1> 	or	dl, 3	; USER + WRITE + PRESENT or SYSTEM + WRITE + PRESENT
  3489 000030C2 0F20D1              <1> 	mov	ecx, cr2 ; CR2 contains the virtual address 
  3490                              <1> 			 ; which has been caused to page fault
  3491                              <1> 			 ;
  3492 000030C5 C1E914              <1> 	shr	ecx, 20	 ; shift 20 bits right
  3493 000030C8 80E1FC              <1> 	and	cl, 0FCh ; mask lower 2 bits to get PDE offset		
  3494                              <1> 	;
  3495 000030CB 01CB                <1> 	add	ebx, ecx ; now, EBX points to the relevant page dir entry 
  3496 000030CD 8B0B                <1> 	mov	ecx, [ebx] ; physical (base) address of the page table 	
  3497 000030CF F6C101              <1> 	test	cl, 1	 ; check bit 0 is set (1) or not (0).
  3498 000030D2 740B                <1> 	jz	short pfh_set_pde ; Page directory entry is not valid,
  3499                              <1> 			  	  ; set/validate page directory entry
  3500 000030D4 6681E100F0          <1> 	and	cx, PDE_A_CLEAR ; 0F000h ; Clear attribute bits
  3501 000030D9 89CB                <1> 	mov	ebx, ecx ; Physical address of the page table
  3502 000030DB 89C1                <1> 	mov	ecx, eax ; new page address (physical) 	
  3503 000030DD EB16                <1> 	jmp	short pfh_get_pte
  3504                              <1> pfh_set_pde:
  3505                              <1> 	;; NOTE: Page directories and page tables never be swapped out!
  3506                              <1> 	;;	 (So, we know this PDE is empty or invalid)
  3507                              <1> 	;
  3508 000030DF 08D0                <1> 	or	al, dl	 ; lower 3 bits are used as U/S, R/W, P flags
  3509 000030E1 8903                <1> 	mov	[ebx], eax ; Let's put the new page directory entry here !
  3510 000030E3 30C0                <1> 	xor	al, al	 ; clear lower (3..8) bits
  3511 000030E5 89C3                <1> 	mov	ebx, eax
  3512 000030E7 E8CAFCFFFF          <1> 	call	allocate_page	 ; (allocate a new page)
  3513 000030EC 72AB                <1> 	jc	short pfh_im_err   ; 'insufficient memory' error
  3514                              <1> pfh_spde_1:
  3515                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  3516 000030EE 89C1                <1> 	mov	ecx, eax
  3517 000030F0 E832FDFFFF          <1> 	call	clear_page ; Clear page content
  3518                              <1> pfh_get_pte:
  3519 000030F5 0F20D0              <1> 	mov	eax, cr2 ; virtual address
  3520                              <1> 			 ; which has been caused to page fault
  3521 000030F8 89C7                <1> 	mov	edi, eax ; 20/07/2015
  3522 000030FA C1E80C              <1> 	shr	eax, 12	 ; shift 12 bit right to get 
  3523                              <1> 			 ; higher 20 bits of the page fault address 
  3524 000030FD 25FF030000          <1> 	and	eax, 3FFh ; mask PDE# bits, the result is PTE# (0 to 1023)
  3525 00003102 C1E002              <1> 	shl	eax, 2	; shift 2 bits left to get PTE offset
  3526 00003105 01C3                <1> 	add	ebx, eax ; now, EBX points to the relevant page table entry 
  3527                              <1> ; 24/12/2021
  3528                              <1> ;	mov	eax, [ebx] ; get previous value of pte
  3529                              <1> ;		; bit 0 of EAX is always 0 (otherwise we would not be here)
  3530                              <1> ; 24/12/2021
  3531                              <1> ; ('swap_in' procedure call has been disabled)
  3532                              <1> ;
  3533                              <1> ;	and	eax, eax
  3534                              <1> ;	jz	short pfh_gpte_1
  3535                              <1> ;	; 20/07/2015
  3536                              <1> ;	xchg	ebx, ecx ; new page address (physical)
  3537                              <1> ;	push	ebp ; 20/07/2015
  3538                              <1> ;	mov	ebp, cr2
  3539                              <1> ;		; ECX = physical address of the page table entry
  3540                              <1> ;		; EBX = Memory page address (physical!)
  3541                              <1> ;		; EAX = Swap disk (offset) address
  3542                              <1> ;		; EBP = virtual address (page fault address)
  3543                              <1> ;	call	swap_in
  3544                              <1> ;	pop	ebp
  3545                              <1> ;	jc      short pfh_err_retn
  3546                              <1> ;	xchg	ecx, ebx
  3547                              <1> ;		; EBX = physical address of the page table entry
  3548                              <1> ;		; ECX = new page
  3549                              <1> pfh_gpte_1:
  3550 00003107 08D1                <1> 	or	cl, dl	; lower 3 bits are used as U/S, R/W, P flags
  3551 00003109 890B                <1> 	mov	[ebx], ecx ; Let's put the new page table entry here !
  3552                              <1> pfh_cpp_ok:
  3553                              <1> ; 24/12/2021
  3554                              <1> ; ('add_to_swap_queue' procedure call has been disabled)
  3555                              <1> ;
  3556                              <1> ;	; 20/07/2015
  3557                              <1> ;	mov	ebx, cr2
  3558                              <1> ;	call 	add_to_swap_queue
  3559                              <1> 	;
  3560                              <1> 	; The new PTE (which contains the new page) will be added to 
  3561                              <1> 	; the swap queue, here. 
  3562                              <1> 	; (Later, if memory will become insufficient, 
  3563                              <1> 	; one page will be swapped out which is at the head of 
  3564                              <1> 	; the swap queue by using FIFO and access check methods.)
  3565                              <1> 	;
  3566 0000310B 31C0                <1> 	xor	eax, eax  ; 0
  3567                              <1> 	;
  3568                              <1> pfh_err_retn:
  3569 0000310D 59                  <1> 	pop	ecx
  3570 0000310E 5A                  <1> 	pop	edx
  3571 0000310F 5B                  <1> 	pop	ebx
  3572 00003110 C3                  <1> 	retn 
  3573                              <1> 	
  3574                              <1> copy_page:
  3575                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  3576                              <1> 	; 16/04/2021
  3577                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3578                              <1> 	; 22/09/2015
  3579                              <1> 	; 21/09/2015
  3580                              <1> 	; 19/09/2015
  3581                              <1> 	; 07/09/2015
  3582                              <1> 	; 31/08/2015
  3583                              <1> 	; 20/07/2015
  3584                              <1> 	; 05/05/2015
  3585                              <1> 	; 03/05/2015
  3586                              <1> 	; 18/04/2015
  3587                              <1> 	; 12/04/2015
  3588                              <1> 	; 30/10/2014
  3589                              <1> 	; 18/10/2014 (Retro UNIX 386 v1 - beginning)
  3590                              <1> 	;
  3591                              <1> 	; INPUT -> 
  3592                              <1> 	;	EBX = Virtual (linear) address of source page
  3593                              <1> 	;	     (Page fault address)
  3594                              <1> 	; OUTPUT ->
  3595                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3596                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3597                              <1> 	;	EAX = 0 (CF = 1) 
  3598                              <1> 	;		if there is not a free page to be allocated
  3599                              <1> 	;	(page content of the source page will be copied
  3600                              <1> 	;	onto the target/new page) 	
  3601                              <1> 	;
  3602                              <1> 	; Modified Registers -> ecx, ebx (except EAX)
  3603                              <1> 	;
  3604                              <1> 
  3605                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3606                              <1> 	; INPUT: 
  3607                              <1> 	;	EBX = Virtual (linear) address of source page
  3608                              <1> 	;	     (Page fault address)
  3609                              <1> 	; OUTPUT:
  3610                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF THE ALLOCATED PAGE
  3611                              <1> 	;	(corresponding PAGE TABLE ENTRY is mapped/set)
  3612                              <1> 	;	EAX = 0 (CF = 1) 
  3613                              <1> 	;		if there is not a free page to be allocated
  3614                              <1> 	;	(page content of the source page will be copied
  3615                              <1> 	;	onto the target/new page) 	
  3616                              <1> 	;
  3617                              <1> 	; Modified Registers -> ecx, ebx (except EAX) ; 16/04/2021
  3618                              <1> 	
  3619 00003111 56                  <1> 	push	esi ; *
  3620 00003112 57                  <1> 	push	edi ; **
  3621                              <1> 	; 16/04/2021
  3622                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3623                              <1> 	;push	ebx ; ***
  3624                              <1> 	;push	ecx ; ****
  3625 00003113 31F6                <1> 	xor 	esi, esi
  3626 00003115 C1EB0C              <1> 	shr	ebx, 12 ; shift 12 bits right to get PDE & PTE numbers
  3627 00003118 89D9                <1> 	mov	ecx, ebx ; save page fault address (as 12 bit shifted)
  3628 0000311A C1EB08              <1> 	shr	ebx, 8	 ; shift 8 bits right and then
  3629 0000311D 80E3FC              <1> 	and	bl, 0FCh ; mask lower 2 bits to get PDE offset	
  3630 00003120 89DF                <1> 	mov 	edi, ebx ; save it for the parent of current process
  3631 00003122 031D[F16E0000]      <1> 	add	ebx, [u.pgdir] ; EBX points to the relevant page dir entry 
  3632 00003128 8B03                <1> 	mov	eax, [ebx] ; physical (base) address of the page table
  3633 0000312A 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits 	
  3634 0000312E 89CB                <1> 	mov	ebx, ecx   ; (restore higher 20 bits of page fault address)
  3635 00003130 81E3FF030000        <1> 	and	ebx, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3636 00003136 66C1E302            <1> 	shl	bx, 2	   ; shift 2 bits left to get PTE offset
  3637 0000313A 01C3                <1> 	add	ebx, eax   ; EBX points to the relevant page table entry 
  3638                              <1> 	; 07/09/2015
  3639 0000313C 66F7030002          <1>         test    word [ebx], PTE_DUPLICATED ; (Does current process share this
  3640                              <1> 				     ; read only page as a child process?)	
  3641 00003141 7509                <1> 	jnz	short cpp_0 ; yes
  3642 00003143 8B0B                <1> 	mov	ecx, [ebx] ; PTE value
  3643 00003145 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h  ; clear page attributes
  3644 0000314A EB32                <1> 	jmp	short cpp_1
  3645                              <1> cpp_0:
  3646 0000314C 89FE                <1> 	mov	esi, edi
  3647 0000314E 0335[F56E0000]      <1> 	add	esi, [u.ppgdir] ; the parent's page directory entry
  3648 00003154 8B06                <1> 	mov	eax, [esi] ; physical (base) address of the page table
  3649 00003156 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3650 0000315A 89CE                <1> 	mov	esi, ecx   ; (restore higher 20 bits of page fault address)	
  3651 0000315C 81E6FF030000        <1> 	and	esi, 3FFh  ; mask PDE# bits, the result is PTE# (0 to 1023)
  3652 00003162 66C1E602            <1> 	shl	si, 2	   ; shift 2 bits left to get PTE offset
  3653 00003166 01C6                <1> 	add	esi, eax   ; EDX points to the relevant page table entry  	
  3654 00003168 8B0E                <1> 	mov	ecx, [esi] ; PTE value of the parent process
  3655                              <1> 	; 21/09/2015
  3656 0000316A 8B03                <1> 	mov	eax, [ebx] ; PTE value of the child process
  3657 0000316C 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear page attributes	
  3658                              <1> 	;
  3659 00003170 F6C101              <1> 	test	cl, PTE_A_PRESENT ; is it a present/valid page ?
  3660 00003173 7424                <1> 	jz	short cpp_3 ; the parent's page is not same page  	
  3661                              <1> 	;
  3662 00003175 6681E100F0          <1> 	and	cx, PTE_A_CLEAR ; 0F000h ; clear page attributes
  3663 0000317A 39C8                <1> 	cmp	eax, ecx   ; Same page?	
  3664 0000317C 751B                <1> 	jne	short cpp_3 ; Parent page and child page are not same 
  3665                              <1> 			    ; Convert child's page to writable page
  3666                              <1> cpp_1:
  3667 0000317E E833FCFFFF          <1> 	call	allocate_page
  3668 00003183 721A                <1> 	jc	short cpp_4 ; 'insufficient memory' error
  3669 00003185 21F6                <1> 	and	esi, esi    ; check ESI is valid or not
  3670 00003187 7405                <1> 	jz	short cpp_2
  3671                              <1> 		; Convert read only page to writable page 
  3672                              <1> 		;(for the parent of the current process)
  3673                              <1> 	;and	word [esi], PTE_A_CLEAR ; 0F000h
  3674                              <1> 	; 22/09/2015
  3675 00003189 890E                <1> 	mov	[esi], ecx
  3676 0000318B 800E07              <1> 	or	byte [esi], PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER
  3677                              <1> 				 ; 1+2+4 = 7
  3678                              <1> cpp_2:
  3679 0000318E 89C7                <1> 	mov	edi, eax ; new page address of the child process
  3680                              <1> 	; 07/09/2015
  3681 00003190 89CE                <1> 	mov	esi, ecx ; the page address of the parent process
  3682 00003192 B900040000          <1> 	mov	ecx, PAGE_SIZE / 4
  3683 00003197 F3A5                <1> 	rep	movsd ; 31/08/2015
  3684                              <1> cpp_3:		
  3685 00003199 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_WRITE + PTE_A_USER ; 1+2+4 = 7
  3686 0000319B 8903                <1> 	mov	[ebx], eax ; Update PTE
  3687 0000319D 28C0                <1> 	sub	al, al ; clear attributes
  3688                              <1> cpp_4:
  3689                              <1> 	; 16/04/2021
  3690                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  3691                              <1> 	;pop	ecx ; ****
  3692                              <1> 	;pop	ebx ; ***
  3693 0000319F 5F                  <1> 	pop	edi ; **
  3694 000031A0 5E                  <1> 	pop	esi ; *
  3695 000031A1 C3                  <1> 	retn
  3696                              <1> 
  3697                              <1> ;; 28/04/2015
  3698                              <1> ;; 24/10/2014
  3699                              <1> ;; 21/10/2014 (Retro UNIX 386 v1 - beginning)
  3700                              <1> ;; SWAP_PAGE_QUEUE (4096 bytes)
  3701                              <1> ;;
  3702                              <1> ;;   0000   0001   0002   0003   ....   1020   1021   1022   1023	
  3703                              <1> ;; +------+------+------+------+-    -+------+------+------+------+
  3704                              <1> ;; |  pg1 |  pg2 |  pg3 |  pg4 | .... |pg1021|pg1022|pg1023|pg1024|
  3705                              <1> ;; +------+------+------+------+-    -+------+------+------+------+    
  3706                              <1> ;;
  3707                              <1> ;; [swpq_last] = 0 to 4096 (step 4) -> the last position on the queue
  3708                              <1> ;;
  3709                              <1> ;; Method:
  3710                              <1> ;;	Swap page queue is a list of allocated pages with physical
  3711                              <1> ;;	addresses (system mode virtual adresses = physical addresses).
  3712                              <1> ;;	It is used for 'swap_in' and 'swap_out' procedures.
  3713                              <1> ;;	When a new page is being allocated, swap queue is updated
  3714                              <1> ;;	by 'swap_queue_shift' procedure, header of the queue (offset 0)
  3715                              <1> ;;	is checked for 'accessed' flag. If the 1st page on the queue
  3716                              <1> ;;	is 'accessed' or 'read only', it is dropped from the list;
  3717                              <1> ;;	other pages from the 2nd to the last (in [swpq_last]) shifted
  3718                              <1> ;; 	to head then the 2nd page becomes the 1st and '[swpq_last]' 
  3719                              <1> ;;	offset value becomes it's previous offset value - 4.
  3720                              <1> ;;	If the 1st page of the swap page queue is not 'accessed'	
  3721                              <1> ;;	the queue/list is not shifted.
  3722                              <1> ;;	After the queue/list shift, newly allocated page is added
  3723                              <1> ;;	to the tail of the queue at the [swpq_count*4] position.
  3724                              <1> ;;	But, if [swpq_count] > 1023, the newly allocated page
  3725                              <1> ;;	will not be added to the tail of swap page queue.  		 
  3726                              <1> ;;	
  3727                              <1> ;;	During 'swap_out' procedure, swap page queue is checked for
  3728                              <1> ;;	the first non-accessed, writable page in the list, 
  3729                              <1> ;;	from the head to the tail. The list is shifted to left 
  3730                              <1> ;;	(to the head) till a non-accessed page will be found in the list.
  3731                              <1> ;;	Then, this page	is swapped out (to disk) and then it is dropped
  3732                              <1> ;;	from the list by a final swap queue shift. [swpq_count] value
  3733                              <1> ;;	is changed. If all pages on the queue' are 'accessed', 
  3734                              <1> ;;	'insufficient memory' error will be returned ('swap_out' 
  3735                              <1> ;;	procedure will be failed)...
  3736                              <1> ;;
  3737                              <1> ;;	Note: If the 1st page of the queue is an 'accessed' page,
  3738                              <1> ;;	'accessed' flag of the page will be reset (0) and that page
  3739                              <1> ;;	(PTE) will be added to the tail of the queue after
  3740                              <1> ;;	the check, if [swpq_count] < 1023. If [swpq_count] = 1024
  3741                              <1> ;;	the queue will be rotated and the PTE in the head will be
  3742                              <1> ;;	added to the tail after resetting 'accessed' bit. 
  3743                              <1> ;;
  3744                              <1> ;;
  3745                              <1> ;;	
  3746                              <1> ;; SWAP DISK/FILE (with 4096 bytes swapped page blocks)
  3747                              <1> ;;
  3748                              <1> ;;  00000000  00000004  00000008  0000000C   ...   size-8    size-4
  3749                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+
  3750                              <1> ;; |descriptr| page(1) | page(2) | page(3) | ... |page(n-1)| page(n) |
  3751                              <1> ;; +---------+---------+---------+---------+-- --+---------+---------+    
  3752                              <1> ;;
  3753                              <1> ;; [swpd_next] = the first free block address in swapped page records
  3754                              <1> ;;    		 for next free block search by 'swap_out' procedure.
  3755                              <1> ;; [swpd_size] = swap disk/file size in sectors (512 bytes)
  3756                              <1> ;;		 NOTE: max. possible swap disk size is 1024 GB
  3757                              <1> ;; 		 (entire swap space must be accessed by using
  3758                              <1> ;;		 31 bit offset address) 
  3759                              <1> ;; [swpd_free] = free block (4096 bytes) count in swap disk/file space
  3760                              <1> ;; [swpd_start] = absolute/start address of the swap disk/file
  3761                              <1> ;;		  0 for file, or beginning sector of the swap partition
  3762                              <1> ;; [swp_drv] = logical drive description table addr. of swap disk/file
  3763                              <1> ;;
  3764                              <1> ;; 					
  3765                              <1> ;; Method:
  3766                              <1> ;;	When the memory (ram) becomes insufficient, page allocation
  3767                              <1> ;;	procedure swaps out a page from memory to the swap disk 
  3768                              <1> ;;	(partition) or swap file to get a new free page at the memory.
  3769                              <1> ;;	Swapping out is performed by using swap page queue.
  3770                              <1> ;;
  3771                              <1> ;; 	Allocation block size of swap disk/file is equal to page size
  3772                              <1> ;;	(4096 bytes). Swapping address (in sectors) is recorded
  3773                              <1> ;;	into relevant page file entry as 31 bit physical (logical)
  3774                              <1> ;;	offset address as 1 bit shifted to left for present flag (0).
  3775                              <1> ;;	Swapped page address is between 1 and swap disk/file size - 4.	  
  3776                              <1> ;;	Absolute physical (logical) address of the swapped page is 
  3777                              <1> ;;	calculated by adding offset value to the swap partition's 
  3778                              <1> ;;	start address. If the swap device (disk) is a virtual disk 
  3779                              <1> ;;	or it is a file, start address of the swap disk/volume is 0, 
  3780                              <1> ;;	and offset value is equal to absolute (physical or logical)
  3781                              <1> ;;	address/position. (It has not to be ZERO if the swap partition 
  3782                              <1> ;;	is in a partitioned virtual hard disk.) 
  3783                              <1> ;;
  3784                              <1> ;;	Note: Swap addresses are always specified/declared in sectors, 
  3785                              <1> ;;	not in bytes or	in blocks/zones/clusters (4096 bytes) as unit.
  3786                              <1> ;;
  3787                              <1> ;;	Swap disk/file allocation is mapped via 'Swap Allocation Table'
  3788                              <1> ;;	at memory as similar to 'Memory Allocation Table'.
  3789                              <1> ;;
  3790                              <1> ;;	Every bit of Swap Allocation Table repsesents one swap block
  3791                              <1> ;;	(equal to page size) respectively. Bit 0 of the S.A.T. byte 0
  3792                              <1> ;;	is reserved for swap disk/file block 0 as descriptor block
  3793                              <1> ;;	(also for compatibility with PTE). If bit value is ZERO,
  3794                              <1> ;;	it means relevant (respective) block is in use, and, 
  3795                              <1> ;;	of course, if bit value is 1, it means relevant (respective)
  3796                              <1> ;;      swap disk/file block is free.
  3797                              <1> ;;	For example: bit 1 of the byte 128 repsesents block 1025 
  3798                              <1> ;;	(128*8+1) or sector (offset) 8200 on the swap disk or
  3799                              <1> ;;	byte (offset/position) 4198400 in the swap file. 
  3800                              <1> ;;	4GB swap space is represented via 128KB Swap Allocation Table.
  3801                              <1> ;;	Initial layout of Swap Allocation Table is as follows:
  3802                              <1> ;;	------------------------------------------------------------
  3803                              <1> ;;	0111111111111111111111111 .... 11111111111111111111111111111
  3804                              <1> ;;	------------------------------------------------------------
  3805                              <1> ;;	(0 is reserved block, 1s represent free blocks respectively.)
  3806                              <1> ;;	(Note: Allocation cell/unit of the table is bit, not byte)
  3807                              <1> ;;
  3808                              <1> ;;	..............................................................
  3809                              <1> ;;
  3810                              <1> ;;	'swap_out' procedure checks 'free_swap_blocks' count at first,
  3811                              <1> ;;	then it searches Swap Allocation Table if free count is not
  3812                              <1> ;;	zero. From begining the [swpd_next] dword value, the first bit 
  3813                              <1> ;;	position with value of 1 on the table is converted to swap
  3814                              <1> ;;	disk/file offset address, in sectors (not 4096 bytes block).
  3815                              <1> ;;	'ldrv_write' procedure is called with ldrv (logical drive
  3816                              <1> ;;	number of physical swap disk or virtual swap disk)
  3817                              <1> ;;	number, sector offset (not absolute sector -LBA- number),
  3818                              <1> ;;	and sector count (8, 512*8 = 4096) and buffer adress
  3819                              <1> ;;	(memory page). That will be a direct disk write procedure.
  3820                              <1> ;;	(for preventing late memory allocation, significant waiting). 
  3821                              <1> ;;	If disk write procedure returns with error or free count of 
  3822                              <1> ;;	swap blocks is ZERO, 'swap_out' procedure will return with
  3823                              <1> ;;	'insufficient memory error' (cf=1). 
  3824                              <1> ;;
  3825                              <1> ;;	(Note: Even if free swap disk/file blocks was not zero,
  3826                              <1> ;;	any disk write error will not be fixed by 'swap_out' procedure,
  3827                              <1> ;;	in other words, 'swap_out' will not check the table for other
  3828                              <1> ;;	free blocks after a disk write error. It will return to 
  3829                              <1> ;;	the caller with error (CF=1) which means swapping is failed. 
  3830                              <1> ;;
  3831                              <1> ;;	After writing the page on to swap disk/file address/sector,
  3832                              <1> ;;	'swap_out' procedure returns with that swap (offset) sector
  3833                              <1> ;;	address (cf=0). 
  3834                              <1> ;;
  3835                              <1> ;;	..............................................................
  3836                              <1> ;;
  3837                              <1> ;;	'swap_in' procedure loads addressed (relevant) swap disk or
  3838                              <1> ;;	file sectors at specified memory page. Then page allocation
  3839                              <1> ;;	procedure updates relevant page table entry with 'present' 
  3840                              <1> ;;	attribute. If swap disk or file reading fails there is nothing
  3841                              <1> ;;	to do, except to terminate the process which is the owner of
  3842                              <1> ;;	the swapped page.
  3843                              <1> ;;
  3844                              <1> ;;	'swap_in' procedure sets the relevant/respective bit value
  3845                              <1> ;;	in the Swap Allocation Table (as free block). 'swap_in' also
  3846                              <1> ;;	updates [swpd_first] pointer if it is required.
  3847                              <1> ;;
  3848                              <1> ;;	..............................................................	 
  3849                              <1> ;;
  3850                              <1> ;;	Note: If [swap_enabled] value is ZERO, that means there is not
  3851                              <1> ;;	a swap disk or swap file in use... 'swap_in' and 'swap_out'
  3852                              <1> ;;	procedures ans 'swap page que' procedures will not be active...
  3853                              <1> ;;	'Insufficient memory' error will be returned by 'swap_out'
  3854                              <1> ;;	and 'general protection fault' will be returned by 'swap_in'
  3855                              <1> ;;	procedure, if it is called mistakenly (a wrong value in a PTE).		
  3856                              <1> ;;
  3857                              <1> 
  3858                              <1> ; 24/12/2021
  3859                              <1> ; ('swap_in' procedure call is disabled)
  3860                              <1> 
  3861                              <1> ;swap_in:
  3862                              <1> 	; 31/08/2015
  3863                              <1> 	; 20/07/2015
  3864                              <1> 	; 28/04/2015
  3865                              <1> 	; 18/04/2015
  3866                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  3867                              <1> 	;
  3868                              <1> 	; INPUT -> 
  3869                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS OF THE MEMORY PAGE
  3870                              <1> 	;	EBP = VIRTUAL (LINEAR) ADDRESS (page fault address)
  3871                              <1> 	;	EAX = Offset Address for the swapped page on the
  3872                              <1> 	;	      swap disk or in the swap file.
  3873                              <1> 	;
  3874                              <1> 	; OUTPUT ->
  3875                              <1> 	;	EAX = 0 if loading at memory has been successful
  3876                              <1> 	;
  3877                              <1> 	;	CF = 1 -> swap disk reading error (disk/file not present
  3878                              <1> 	;		  or sector not present or drive not ready
  3879                              <1> 	;	     EAX = Error code
  3880                              <1> 	;	     [u.error] = EAX 
  3881                              <1> 	;		       = The last error code for the process
  3882                              <1> 	;		         (will be reset after returning to user)	  
  3883                              <1> 	;
  3884                              <1> 	; Modified Registers -> EAX
  3885                              <1> 	;
  3886                              <1> 
  3887                              <1> ;       cmp     dword [swp_drv], 0
  3888                              <1> ;	jna	short swpin_dnp_err
  3889                              <1> ;
  3890                              <1> ;	cmp	eax, [swpd_size]
  3891                              <1> ;	jnb	short swpin_snp_err
  3892                              <1> ;
  3893                              <1> ;	push	esi
  3894                              <1> ;	push	ebx
  3895                              <1> ;	push	ecx
  3896                              <1> ;	mov	esi, [swp_drv]	
  3897                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  3898                              <1> ;		; Note: Even if corresponding physical disk's sector 
  3899                              <1> ;		; size different than 512 bytes, logical disk sector
  3900                              <1> ;		; size is 512 bytes and disk reading procedure
  3901                              <1> ;		; will be performed for reading 4096 bytes
  3902                              <1> ;		; (2*2048, 8*512). 
  3903                              <1> ;	; ESI = Logical disk description table address
  3904                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3905                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  3906                              <1> ;	; ECX = Sector count ; 8 sectors
  3907                              <1> ;	push	eax
  3908                              <1> ;	call	logical_disk_read
  3909                              <1> ;	pop	eax
  3910                              <1> ;	jnc	short swpin_read_ok
  3911                              <1> ;	;
  3912                              <1> ;	mov	eax, SWP_DISK_READ_ERR ; drive not ready or read error
  3913                              <1> ;	mov	[u.error], eax
  3914                              <1> ;	jmp	short swpin_retn
  3915                              <1> ;	;
  3916                              <1> ;swpin_read_ok:
  3917                              <1> ;	; EAX = Offset address (logical sector number)
  3918                              <1> ;	call	unlink_swap_block  ; Deallocate swap block	
  3919                              <1> ;	;
  3920                              <1> ;	; EBX = Memory page (buffer) address (physical!)
  3921                              <1> ;	; 20/07/2015
  3922                              <1> ;	mov	ebx, ebp ; virtual address (page fault address)
  3923                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  3924                              <1> ;	mov	bl, [u.uno] ; current process number
  3925                              <1> ;	; EBX = Virtual (Linear) address & process number combination
  3926                              <1> ;	call	swap_queue_shift
  3927                              <1> ;	; eax = 0 ; 10/06/2016 (if ebx input > 0, eax output = 0)
  3928                              <1> ;	;sub	eax, eax  ; 0 ; Error Code = 0  (no error)
  3929                              <1> ;	; zf = 1
  3930                              <1> ;swpin_retn:
  3931                              <1> ;	pop	ecx
  3932                              <1> ;	pop	ebx
  3933                              <1> ;	pop	esi
  3934                              <1> ;	retn
  3935                              <1> ;
  3936                              <1> ;swpin_dnp_err:
  3937                              <1> ;	mov	eax, SWP_DISK_NOT_PRESENT_ERR
  3938                              <1> ;swpin_err_retn:
  3939                              <1> ;	mov	[u.error], eax
  3940                              <1> ;	stc
  3941                              <1> ;	retn
  3942                              <1> ;
  3943                              <1> ;swpin_snp_err:
  3944                              <1> ;	mov	eax, SWP_SECTOR_NOT_PRESENT_ERR
  3945                              <1> ;	jmp	short swpin_err_retn
  3946                              <1> 
  3947                              <1> ; 24/12/2021
  3948                              <1> ; ('swap_out' procedure call is disabled)
  3949                              <1> 
  3950                              <1> ;swap_out:
  3951                              <1> 	; 10/06/2016
  3952                              <1> 	; 07/06/2016
  3953                              <1>         ; 23/05/2016
  3954                              <1> 	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
  3955                              <1> 	; 24/10/2014 - 31/08/2015 (Retro UNIX 386 v1)
  3956                              <1> 	;
  3957                              <1> 	; INPUT -> 
  3958                              <1> 	;	none
  3959                              <1> 	;
  3960                              <1> 	; OUTPUT ->
  3961                              <1> 	;	EAX = Physical page address (which is swapped out
  3962                              <1> 	;	      for allocating a new page)
  3963                              <1> 	;	CF = 1 -> swap disk writing error (disk/file not present
  3964                              <1> 	;		  or sector not present or drive not ready
  3965                              <1> 	;	     EAX = Error code
  3966                              <1> 	;	     [u.error] = EAX 
  3967                              <1> 	;		       = The last error code for the process
  3968                              <1> 	;		         (will be reset after returning to user)	  
  3969                              <1> 	;
  3970                              <1> 	; Modified Registers -> none (except EAX)
  3971                              <1> 	;
  3972                              <1> 
  3973                              <1> ;	cmp 	word [swpq_count], 1
  3974                              <1> ;       jc      swpout_im_err ; 'insufficient memory'
  3975                              <1> ;
  3976                              <1> ;       ;cmp    dword [swp_drv], 1
  3977                              <1> ;	;jc	short swpout_dnp_err ; 'swap disk/file not present'
  3978                              <1> ;
  3979                              <1> ;       cmp     dword [swpd_free], 1
  3980                              <1> ;       jc      swpout_nfspc_err ; 'no free space on swap disk'
  3981                              <1> ;
  3982                              <1> ;	push	ebx ; *
  3983                              <1> ;swpout_1:
  3984                              <1> ;	; 10/06/2016
  3985                              <1> ;	xor	ebx, ebx ; shift the queue and return a PTE value
  3986                              <1> ;	call	swap_queue_shift
  3987                              <1> ;	and	eax, eax	; 0 = empty queue (improper entries)
  3988                              <1> ;       jz      swpout_npts_err        ; There is not any proper PTE
  3989                              <1> ;				       ; pointer in the swap queue
  3990                              <1> ;	; EAX = PTE value of the page
  3991                              <1> ;	; EBX = PTE address of the page
  3992                              <1> ;	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  3993                              <1> ;	;
  3994                              <1> ;	; 07/06/2016
  3995                              <1> ;	; 19/05/2016
  3996                              <1> ;	; check this page is in timer events or not
  3997                              <1> ;	
  3998                              <1> ;swpout_timer_page_0:
  3999                              <1> ;	push	edx ; **
  4000                              <1> ;
  4001                              <1> ;	; 07/06/2016
  4002                              <1> ;	cmp	byte [timer_events], 0 
  4003                              <1> ;	jna	short swpout_2
  4004                              <1> ;	;
  4005                              <1> ;	mov	dl, [timer_events]
  4006                              <1> ;
  4007                              <1> ;	push	ecx ; ***
  4008                              <1> ;	push	ebx ; ****
  4009                              <1> ;	mov	ebx, timer_set ; beginning address of timer event
  4010                              <1> ;			       ; structures 
  4011                              <1> ;swpout_timer_page_1:
  4012                              <1> ;	mov	cl, [ebx]
  4013                              <1> ;	or	cl, cl ; 0 = free, >0 = process number
  4014                              <1> ;	jz	short swpout_timer_page_3
  4015                              <1> ;	mov	ecx, [ebx+12] ; response (signal return) address
  4016                              <1> ;	and	cx, PTE_A_CLEAR ; clear offset part (right 12 bits)
  4017                              <1> ;				; of the response byte address, to
  4018                              <1> ;				; get beginning of the page address)
  4019                              <1> ;	cmp	eax, ecx
  4020                              <1> ;	jne	short swpout_timer_page_2 ; not same page
  4021                              <1> ;	
  4022                              <1> ;	; !same page!
  4023                              <1> ;	;
  4024                              <1> ;	; NOTE: // 19/05/2016 // - TRDOS 386 feature only ! -
  4025                              <1> ;	; This page will be used by the kernel to put timer event
  4026                              <1> ;	; response (signal return) byte at the requested address;
  4027                              <1> ;	; in order to prevent a possible wrong write (while
  4028                              <1> ;	; this page is swapped out) on physical memory,
  4029                              <1> ;	; we must protect this page against to be swapped out!
  4030                              <1> ;	;
  4031                              <1> ;	pop	ebx ; ****
  4032                              <1> ;	pop	ecx ; ***
  4033                              <1> ;	pop	edx ; **
  4034                              <1> ;	jmp	short swpout_1	; do not swap out this page !
  4035                              <1> ; 
  4036                              <1> ;swpout_timer_page_2:
  4037                              <1> ;	; 07/06/2016
  4038                              <1> ;	dec	dl
  4039                              <1> ;	jz	short swpout_timer_page_4
  4040                              <1> ;swpout_timer_page_3:
  4041                              <1> ;	;cmp	ebx, timer_set + 240 ; last timer event (15*16) 
  4042                              <1> ;	;jnb	short swpout_timer_page_4
  4043                              <1> ;	add	ebx, 16
  4044                              <1> ;	jmp	short swpout_timer_page_1	
  4045                              <1> ;
  4046                              <1> ;swpout_timer_page_4:
  4047                              <1> ;	pop	ebx ; ****
  4048                              <1> ;	pop	ecx ; ***
  4049                              <1> ;swpout_2:
  4050                              <1> ;	mov	edx, ebx	       ; Page table entry address	
  4051                              <1> ;	mov	ebx, eax	       ; Buffer (Page) Address				
  4052                              <1> ;	;
  4053                              <1> ;	call	link_swap_block
  4054                              <1> ;	jnc	short swpout_3	       ; It may not be needed here	
  4055                              <1> ;				       ; because [swpd_free] value
  4056                              <1> ;				       ; was checked at the beginging. 	
  4057                              <1> ;	pop	edx ; **
  4058                              <1> ;	pop	ebx ; *
  4059                              <1> ;	jmp	short swpout_nfspc_err 
  4060                              <1> ;swpout_3:
  4061                              <1> ;	test	eax, 80000000h ; test bit 31 (this may not be needed!)
  4062                              <1> ;	jnz	short swpout_nfspc_err  ; 10/06/2016 (bit 31 = 1 !)
  4063                              <1> ;	;	
  4064                              <1> ;	push	esi ; **
  4065                              <1> ;	push	ecx ; ***
  4066                              <1> ;	push	eax ; sector address ; (31 bit !, bit 31 = 0)
  4067                              <1> ;	mov	esi, [swp_drv]	
  4068                              <1> ;	mov	ecx, PAGE_SIZE / LOGIC_SECT_SIZE  ; 8 !
  4069                              <1> ;		; Note: Even if corresponding physical disk's sector 
  4070                              <1> ;		; size different than 512 bytes, logical disk sector
  4071                              <1> ;		; size is 512 bytes and disk writing procedure
  4072                              <1> ;		; will be performed for writing 4096 bytes
  4073                              <1> ;		; (2*2048, 8*512). 
  4074                              <1> ;	; ESI = Logical disk description table address
  4075                              <1> ;	; EBX = Buffer (Page) address
  4076                              <1> ;	; EAX = Sector adress (offset address, logical sector number)
  4077                              <1> ;	; ECX = Sector count ; 8 sectors
  4078                              <1> ;	; edx = PTE address
  4079                              <1> ;	call	logical_disk_write
  4080                              <1> ;	; edx = PTE address
  4081                              <1> ;	pop	ecx ; sector address	
  4082                              <1> ;	jnc	short swpout_write_ok
  4083                              <1> ;	;
  4084                              <1> ;	;; call	unlink_swap_block ; this block must be left as 'in use'
  4085                              <1> ;swpout_dw_err:
  4086                              <1> ;	mov	eax, SWP_DISK_WRITE_ERR ; drive not ready or write error
  4087                              <1> ;	mov	[u.error], eax
  4088                              <1> ;	jmp	short swpout_retn
  4089                              <1> ;	;
  4090                              <1> ;swpout_write_ok:
  4091                              <1> ;	; EBX = Buffer (page) address
  4092                              <1> ;	; EDX = Page Table Entry address
  4093                              <1> ;	; ECX = Swap disk sector (file block) address (31 bit)
  4094                              <1> ;	shl 	ecx, 1  ; 31 bit sector address from bit 1 to bit 31 
  4095                              <1> ;	mov 	[edx], ecx 
  4096                              <1> ;		; bit 0 = 0 (swapped page)
  4097                              <1> ;	mov	eax, ebx
  4098                              <1> ;swpout_retn:
  4099                              <1> ;	pop	ecx ; ***
  4100                              <1> ;	pop	esi ; **
  4101                              <1> ;	pop	ebx ; *
  4102                              <1> ;	retn
  4103                              <1> ;
  4104                              <1> ;;swpout_dnp_err:
  4105                              <1> ;;	mov	eax, SWP_DISK_NOT_PRESENT_ERR ; disk not present
  4106                              <1> ;;	jmp	short swpout_err_retn
  4107                              <1> ;swpout_nfspc_err:
  4108                              <1> ;	mov	eax, SWP_NO_FREE_SPACE_ERR ; no free space
  4109                              <1> ;swpout_err_retn:
  4110                              <1> ;	mov	[u.error], eax
  4111                              <1> ;	;stc
  4112                              <1> ;	retn
  4113                              <1> ;swpout_npts_err:
  4114                              <1> ;	mov	eax, SWP_NO_PAGE_TO_SWAP_ERR
  4115                              <1> ;	pop	ebx
  4116                              <1> ;	jmp	short swpout_err_retn
  4117                              <1> ;swpout_im_err:
  4118                              <1> ;	mov	eax, ERR_MINOR_IM ; insufficient (out of) memory
  4119                              <1> ;	jmp	short swpout_err_retn
  4120                              <1> 
  4121                              <1> ; 24/12/2021
  4122                              <1> ; ('swap_queue_shift' procedure call is disabled)
  4123                              <1> 
  4124                              <1> ;swap_queue_shift:
  4125                              <1> 	; 26/03/2017
  4126                              <1> 	; 10/06/2016
  4127                              <1> 	; 09/06/2016 - TRDOS 386 (TRDOS v2.0)
  4128                              <1> 	; 23/10/2014 - 20/07/2015 (Retro UNIX 386 v1)
  4129                              <1> 	;
  4130                              <1> 	; INPUT ->
  4131                              <1> 	;	EBX = Virtual (linear) address (bit 12 to 31) 
  4132                              <1> 	;	      and process number combination (bit 0 to 11)
  4133                              <1> 	;	EBX = 0 -> shift/drop from the head (offset 0)
  4134                              <1> 	;	
  4135                              <1> 	; OUTPUT ->
  4136                              <1> 	;	If EBX input > 0 
  4137                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4138                              <1> 	; 	   from the tail to the head, up to entry offset
  4139                              <1> 	; 	   which points to EBX input value or nothing
  4140                              <1> 	;	   to do if EBX value is not found on the queue.
  4141                              <1> 	;	   (The entry -with EBX value- will be removed
  4142                              <1> 	;	   from the queue if it is found.)
  4143                              <1> 	;
  4144                              <1> 	;	   EAX = 0		
  4145                              <1> 	;
  4146                              <1> 	;	If EBX input = 0
  4147                              <1> 	;	   the queue will be shifted 4 bytes (dword),
  4148                              <1> 	; 	   from the tail to the head, if the PTE address
  4149                              <1> 	;	   which is pointed in head of the queue is marked
  4150                              <1> 	;	   as "accessed" or it is marked as "non present".
  4151                              <1> 	;	   (If "accessed" flag of the PTE -which is pointed
  4152                              <1> 	;	   in the head- is set -to 1-, it will be reset
  4153                              <1> 	;	   -to 0- and then, the queue will be rotated 
  4154                              <1> 	;	   -without dropping pointer of the PTE from 
  4155                              <1> 	;	   the queue- for 4 bytes on head to tail direction.
  4156                              <1> 	;	   Pointer in the head will be moved into the tail,
  4157                              <1> 	;	   other PTEs will be shifted on head direction.)
  4158                              <1> 	;
  4159                              <1> 	;	   Swap queue will be shifted up to the first
  4160                              <1> 	;	   'present' or 'non accessed' page will be found
  4161                              <1> 	;	   (as pointed) on the queue head (then it will be
  4162                              <1>         ;          removed/dropped from the queue).
  4163                              <1> 	;
  4164                              <1> 	;	   EAX (> 0) = PTE value of the page which is
  4165                              <1> 	;		 (it's pointer -virtual address-) dropped
  4166                              <1> 	;		 (removed) from swap queue.
  4167                              <1> 	;	   EBX = PTE address of the page (if EAX > 0)
  4168                              <1> 	;	         which is (it's pointer -virtual address-)
  4169                              <1> 	;		 dropped (removed) from swap queue.
  4170                              <1> 	;
  4171                              <1> 	;	   EAX = 0 -> empty swap queue ! 
  4172                              <1> 	;
  4173                              <1> 	; Modified Registers -> EAX, EBX
  4174                              <1> 	;
  4175                              <1> ;	movzx   eax, word [swpq_count]  ; Max. 1024
  4176                              <1> ;	and	ax, ax
  4177                              <1> ;	jz	short swpqs_retn
  4178                              <1> ;	push	edi
  4179                              <1> ;	push	esi
  4180                              <1> ;	push	ecx
  4181                              <1> ;	mov	esi, swap_queue
  4182                              <1> ;	mov	ecx, eax
  4183                              <1> ;	or	ebx, ebx
  4184                              <1> ;	jz	short swpqs_7
  4185                              <1> ;swpqs_1:
  4186                              <1> ;	lodsd
  4187                              <1> ;	cmp	eax, ebx
  4188                              <1> ;	je	short swpqs_2
  4189                              <1> ;	loop	swpqs_1
  4190                              <1> ;	; 10/06/2016
  4191                              <1> ;	sub	eax, eax 
  4192                              <1> ;	jmp	short swpqs_6
  4193                              <1> ;swpqs_2:
  4194                              <1> ;	mov	edi, esi
  4195                              <1> ;	sub 	edi, 4
  4196                              <1> ;swpqs_3:
  4197                              <1> ;	dec	word [swpq_count]
  4198                              <1> ;	jz	short swpqs_5
  4199                              <1> ;swpqs_4:
  4200                              <1> ;	dec 	ecx
  4201                              <1> ;	rep	movsd	; shift up (to the head)
  4202                              <1> ;swpqs_5:
  4203                              <1> ;	xor	eax, eax
  4204                              <1> ;	mov	[edi], eax
  4205                              <1> ;swpqs_6:
  4206                              <1> ;	pop	ecx
  4207                              <1> ;	pop	esi
  4208                              <1> ;	pop	edi
  4209                              <1> ;swpqs_retn:
  4210                              <1> ;	retn		
  4211                              <1> ;swpqs_7:
  4212                              <1> ;	mov	edi, esi ; head
  4213                              <1> ;	lodsd
  4214                              <1> ;	; 20/07/2015
  4215                              <1> ;	mov	ebx, eax
  4216                              <1> ;	and	ebx, ~PAGE_OFF ; ~0FFFh 
  4217                              <1> ;		      ; ebx = virtual address (at page boundary)	
  4218                              <1> ;	and	eax, PAGE_OFF ; 0FFFh
  4219                              <1> ;		      ; ax = process number (1 to 4095)
  4220                              <1> ;	cmp	al, [u.uno]
  4221                              <1> ;		; Max. 16 (nproc) processes for Retro UNIX 386 v1
  4222                              <1> ;	jne	short swpqs_8
  4223                              <1> ;	mov	eax, [u.pgdir]
  4224                              <1> ;	jmp	short swpqs_9
  4225                              <1> ;swpqs_8:
  4226                              <1> ;	; 09/06/2016
  4227                              <1> ;	cmp	byte [eax+p.stat-1], 0
  4228                              <1> ;	jna	short swpqs_3     ; free (or terminated) process
  4229                              <1> ;	cmp	byte [eax+p.stat-1], 2 ; waiting
  4230                              <1> ;	ja	short swpqs_3 	  ; zombie (3) or undefined ?	
  4231                              <1> ;
  4232                              <1> ;	;shl	ax, 2
  4233                              <1> ;	shl	al, 2
  4234                              <1> ;	mov 	eax, [eax+p.upage-4]
  4235                              <1> ;	or	eax, eax
  4236                              <1> ;	jz	short swpqs_3 ; invalid upage
  4237                              <1> ;	add	eax, u.pgdir - user
  4238                              <1> ;			 ; u.pgdir value for the process
  4239                              <1> ;			 ; is in [eax]
  4240                              <1> ;	mov	eax, [eax]
  4241                              <1> ;	and	eax, eax
  4242                              <1> ;	jz	short swpqs_3 ; invalid page directory
  4243                              <1> ;swpqs_9:
  4244                              <1> ;	push	edx
  4245                              <1> ;	; eax = page directory
  4246                              <1> ;	; ebx = virtual address
  4247                              <1> ;	call	get_pte
  4248                              <1> ;	mov	ebx, edx	; PTE address
  4249                              <1> ;	pop	edx
  4250                              <1> ;	; 10/06/2016
  4251                              <1> ;	jc	short swpqs_13 ; empty PDE
  4252                              <1> ;	; EAX = PTE value
  4253                              <1> ;	test	al, PTE_A_PRESENT ; bit 0 = 1
  4254                              <1> ;	jz	short swpqs_13  ; Drop non-present page
  4255                              <1> ;			        ; from the queue (head)
  4256                              <1> ;	test	al, PTE_A_WRITE	; bit 1 = 0 (read only)
  4257                              <1> ;	jz	short swpqs_13  ; Drop read only page
  4258                              <1> ;			        ; from the queue (head) 	
  4259                              <1> ;	;test	al, PTE_A_ACCESS ; bit 5 = 1 (Accessed)
  4260                              <1> ;	;jnz	short swpqs_11  ; present
  4261                              <1> ;			        ; accessed page
  4262                              <1> ;       btr     eax, PTE_A_ACCESS_BIT ; reset 'accessed' bit
  4263                              <1> ;	jc	short swpqs_11  ; accessed page
  4264                              <1> ;
  4265                              <1> ;	dec	ecx
  4266                              <1> ;	mov	[swpq_count], cx
  4267                              <1> ;       jz      short swpqs_10
  4268                              <1> ;		; esi = head + 4
  4269                              <1> ;		; edi = head
  4270                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4271                              <1> ;swpqs_10:
  4272                              <1> ;	mov	[edi], ecx ; 0
  4273                              <1> ;	jmp	short swpqs_6 ; 26/03/2017
  4274                              <1> ;
  4275                              <1> ;swpqs_11:
  4276                              <1> ;	mov	[ebx], eax     ; save changed attribute
  4277                              <1> ;	; Rotation (head -> tail)
  4278                              <1> ;	dec	ecx     ; entry count -> last entry number		
  4279                              <1> ;	jz	short swpqs_10
  4280                              <1> ;		; esi = head + 4
  4281                              <1> ;		; edi = head
  4282                              <1> ;	mov	eax, [edi] ; 20/07/2015
  4283                              <1> ;	rep	movsd	 ; n = 1 to k-1, [n - 1] = [n]
  4284                              <1> ;	mov	[edi], eax ; head -> tail ; [k] = [1]
  4285                              <1> ;
  4286                              <1> ;	mov	cx, [swpq_count]
  4287                              <1> ;
  4288                              <1> ;swpqs_12:
  4289                              <1> ;	mov	esi, swap_queue ; head
  4290                              <1> ;       jmp     swpqs_7
  4291                              <1> ;
  4292                              <1> ;swpqs_13:
  4293                              <1> ;	dec	ecx
  4294                              <1> ;	mov	[swpq_count], cx
  4295                              <1> ;       jz      swpqs_5
  4296                              <1> ;	jmp	short swpqs_12
  4297                              <1> 
  4298                              <1> ; 24/12/2021
  4299                              <1> ; ('add_to_swp_queue' procedure call is disabled)
  4300                              <1> 
  4301                              <1> ;add_to_swap_queue:
  4302                              <1> 	; 20/02/2017
  4303                              <1> 	; 20/07/2015
  4304                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4305                              <1> 	;
  4306                              <1> 	; Adds new page to swap queue
  4307                              <1> 	; (page directories and page tables must not be added
  4308                              <1> 	; to swap queue)	
  4309                              <1> 	;
  4310                              <1> 	; INPUT ->
  4311                              <1> 	;	EBX = Linear (Virtual) addr for current process
  4312                              <1> 	;	[u.uno]
  4313                              <1> 	;	20/02/2017
  4314                              <1> 	;	(Linear address = CORE + user's virtual address)
  4315                              <1> 	;
  4316                              <1> 	; OUTPUT ->
  4317                              <1> 	;	EAX = [swpq_count]
  4318                              <1> 	;	      (after the PTE has been added)
  4319                              <1> 	;	EAX = 0 -> Swap queue is full, (1024 entries)
  4320                              <1> 	;	      the PTE could not be added.
  4321                              <1> 	;
  4322                              <1> 	; Modified Registers -> EAX
  4323                              <1> 	;
  4324                              <1> ;	push	ebx
  4325                              <1> ;       and     bx, ~PAGE_OFF ; ~0FFFh ; reset bits, 0 to 11
  4326                              <1> ;	mov	bl, [u.uno] ; current process number
  4327                              <1> ;	call	swap_queue_shift ; drop from the queue if
  4328                              <1> ;				 ; it is already on the queue
  4329                              <1> ;		; then add it to the tail of the queue
  4330                              <1> ;	movzx	eax, word [swpq_count]
  4331                              <1> ;	cmp	ax, 1024
  4332                              <1> ;	jb	short atsq_1
  4333                              <1> ;	sub	ax, ax
  4334                              <1> ;	pop	ebx
  4335                              <1> ;	retn
  4336                              <1> ;atsq_1:
  4337                              <1> ;	push	esi
  4338                              <1> ;	mov	esi, swap_queue
  4339                              <1> ;	and	ax, ax
  4340                              <1> ;	jz	short atsq_2
  4341                              <1> ;	shl	ax, 2	; convert to offset
  4342                              <1> ;	add	esi, eax
  4343                              <1> ;	shr	ax, 2
  4344                              <1> ;atsq_2:
  4345                              <1> ;	inc	ax
  4346                              <1> ;	mov	[esi], ebx ; Virtual address + [u.uno] combination
  4347                              <1> ;	mov	[swpq_count], ax
  4348                              <1> ;	pop	esi
  4349                              <1> ;	pop	ebx
  4350                              <1> ;	retn
  4351                              <1> 
  4352                              <1> ; 24/12/2021
  4353                              <1> ; ('unlink_swap_block' procedure call is disabled)
  4354                              <1> 
  4355                              <1> ;unlink_swap_block:
  4356                              <1> 	; 15/09/2015
  4357                              <1> 	; 30/04/2015
  4358                              <1> 	; 18/04/2015
  4359                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4360                              <1> 	;
  4361                              <1> 	; INPUT -> 
  4362                              <1> 	;	EAX = swap disk/file offset address
  4363                              <1> 	;	      (bit 1 to bit 31)
  4364                              <1> 	; OUTPUT ->
  4365                              <1> 	;	[swpd_free] is increased
  4366                              <1> 	;	(corresponding SWAP DISK ALLOC. TABLE bit is SET)
  4367                              <1> 	;
  4368                              <1> 	; Modified Registers -> EAX
  4369                              <1> 	;
  4370                              <1> ;	push	ebx
  4371                              <1> ;	push	edx
  4372                              <1> ;	;
  4373                              <1> ;	shr	eax, SECTOR_SHIFT+1  ;3+1 ; shift sector address to 
  4374                              <1> ;				     ; 3 bits right
  4375                              <1> ;				     ; to get swap block/page number
  4376                              <1> ;	mov	edx, eax
  4377                              <1> ;	; 15/09/2015
  4378                              <1> ;	shr	edx, 3		     ; to get offset to S.A.T.
  4379                              <1> ;				     ; (1 allocation bit = 1 page)
  4380                              <1> ;				     ; (1 allocation bytes = 8 pages)
  4381                              <1> ;	and	dl, 0FCh 	     ; clear lower 2 bits
  4382                              <1> ;				     ; (to get 32 bit position)			
  4383                              <1> ;	;
  4384                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table address
  4385                              <1> ;	add	ebx, edx
  4386                              <1> ;	and	eax, 1Fh	     ; lower 5 bits only
  4387                              <1> ;				     ; (allocation bit position)	 
  4388                              <1> ;	cmp 	eax, [swpd_next]     ; is the new free block addr. lower
  4389                              <1> ;				     ; than the address in 'swpd_next' ?
  4390                              <1> ;				     ; (next/first free block value)		
  4391                              <1> ;	jnb	short uswpbl_1	     ; no	
  4392                              <1> ;	mov	[swpd_next], eax     ; yes	
  4393                              <1> ;uswpbl_1:
  4394                              <1> ;	bts	[ebx], eax	     ; unlink/release/deallocate block
  4395                              <1> ;				     ; set relevant bit to 1.
  4396                              <1> ;				     ; set CF to the previous bit value	
  4397                              <1> ;	cmc			     ; complement carry flag	
  4398                              <1> ;	jc	short uswpbl_2	     ; do not increase swfd_free count
  4399                              <1> ;				     ; if the block is already deallocated
  4400                              <1> ;				     ; before.	
  4401                              <1> ;       inc     dword [swpd_free]
  4402                              <1> ;uswpbl_2:
  4403                              <1> ;	pop	edx
  4404                              <1> ;	pop	ebx
  4405                              <1> ;	retn
  4406                              <1> 
  4407                              <1> ; 24/12/2021
  4408                              <1> ; ('link_swap_block' procedure call is disabled)
  4409                              <1> 
  4410                              <1> ;link_swap_block:
  4411                              <1> 	; 01/07/2015
  4412                              <1> 	; 18/04/2015
  4413                              <1> 	; 24/10/2014 (Retro UNIX 386 v1 - beginning)
  4414                              <1> 	;
  4415                              <1> 	; INPUT -> none
  4416                              <1> 	;
  4417                              <1> 	; OUTPUT ->
  4418                              <1> 	;	EAX = OFFSET ADDRESS OF THE ALLOCATED BLOCK (4096 bytes)
  4419                              <1> 	;	      in sectors (corresponding 
  4420                              <1> 	;	      SWAP DISK ALLOCATION TABLE bit is RESET)
  4421                              <1> 	;
  4422                              <1> 	;	CF = 1 and EAX = 0 
  4423                              <1> 	; 		   if there is not a free block to be allocated	
  4424                              <1> 	;
  4425                              <1> 	; Modified Registers -> none (except EAX)
  4426                              <1> 	;
  4427                              <1> 
  4428                              <1> ;	;mov	eax, [swpd_free]
  4429                              <1> ;	;and	eax, eax
  4430                              <1> ;	;jz	short out_of_swpspc
  4431                              <1> ;	;
  4432                              <1> ;	push	ebx
  4433                              <1> ;	push	ecx
  4434                              <1> ;	;
  4435                              <1> ;	mov	ebx, swap_alloc_table ; Swap Allocation Table offset
  4436                              <1> ;	mov	ecx, ebx
  4437                              <1> ;	add	ebx, [swpd_next] ; Free block searching starts from here
  4438                              <1> ;				 ; next_free_swap_block >> 5
  4439                              <1> ;	add	ecx, [swpd_last] ; Free block searching ends here
  4440                              <1> ;				 ; (total_swap_blocks - 1) >> 5
  4441                              <1> ;lswbl_scan:
  4442                              <1> ;	cmp	ebx, ecx
  4443                              <1> ;	ja	short lswbl_notfound
  4444                              <1> ;	;
  4445                              <1> ;	bsf	eax, [ebx] ; Scans source operand for first bit set (1).
  4446                              <1> ;			   ; Clears ZF if a bit is found set (1) and 
  4447                              <1> ;			   ; loads the destination with an index to
  4448                              <1> ;			   ; first set bit. (0 -> 31) 
  4449                              <1> ;			   ; Sets ZF to 1 if no bits are found set.
  4450                              <1> ;	; 01/07/2015
  4451                              <1> ;	jnz	short lswbl_found ; ZF = 0 -> a free block has been found
  4452                              <1> ;			 ;
  4453                              <1> ;			 ; NOTE:  a Swap Disk Allocation Table bit 
  4454                              <1> ;			 ;	  with value of 1 means 
  4455                              <1> ;			 ;	  the corresponding page is free 
  4456                              <1> ;			 ;	  (Retro UNIX 386 v1 feaure only!)
  4457                              <1> ;	add	ebx, 4
  4458                              <1> ;			 ; We return back for searching next page block
  4459                              <1> ;			 ; NOTE: [swpd_free] is not ZERO; so, 
  4460                              <1> ;			 ;	 we always will find at least 1 free block here.
  4461                              <1> ;	jmp    	short lswbl_scan
  4462                              <1> ;	;
  4463                              <1> ;lswbl_notfound:	
  4464                              <1> ;	sub	ecx, swap_alloc_table
  4465                              <1> ;	mov	[swpd_next], ecx ; next/first free page = last page 
  4466                              <1> ;				 ; (unlink_swap_block procedure will change it)
  4467                              <1> ;	xor	eax, eax
  4468                              <1> ;	mov	[swpd_free], eax
  4469                              <1> ;	stc
  4470                              <1> ;lswbl_ok:
  4471                              <1> ;	pop	ecx
  4472                              <1> ;	pop	ebx
  4473                              <1> ;	retn
  4474                              <1> ;	;
  4475                              <1> ;;out_of_swpspc:
  4476                              <1> ;;	stc
  4477                              <1> ;;	retn
  4478                              <1> ;
  4479                              <1> ;lswbl_found:
  4480                              <1> ;	mov	ecx, ebx
  4481                              <1> ;	sub	ecx, swap_alloc_table
  4482                              <1> ;	mov	[swpd_next], ecx ; Set first free block searching start
  4483                              <1> ;				 ; address/offset (to the next)
  4484                              <1> ;       dec     dword [swpd_free] ; 1 block has been allocated (X = X-1) 
  4485                              <1> ;	;
  4486                              <1> ;	btr	[ebx], eax	 ; The destination bit indexed by the source value
  4487                              <1> ;				 ; is copied into the Carry Flag and then cleared
  4488                              <1> ;				 ; in the destination.
  4489                              <1> ;				 ;
  4490                              <1> ;				 ; Reset the bit which is corresponding to the 
  4491                              <1> ;				 ; (just) allocated block.
  4492                              <1> ;	shl	ecx, 5		 ; (block offset * 32) + block index
  4493                              <1> ;	add	eax, ecx	 ; = block number
  4494                              <1> ;	shl	eax, SECTOR_SHIFT ; 3, sector (offset) address of the block
  4495                              <1> ;				 ; 1 block =  8 sectors
  4496                              <1> ;	;
  4497                              <1> ;	; EAX = offset address of swap disk/file sector (beginning of the block)
  4498                              <1> ;	;
  4499                              <1> ;	; NOTE: The relevant page table entry will be updated
  4500                              <1> ;	;       according to this EAX value...
  4501                              <1> ;	;
  4502                              <1> ;	jmp	short lswbl_ok
  4503                              <1> 
  4504                              <1> ; 24/12/2021
  4505                              <1> ; ('logical_disk_read' procedure call is disabled)
  4506                              <1> 
  4507                              <1> ;logical_disk_read:
  4508                              <1> 	; 20/07/2015
  4509                              <1> 	; 09/03/2015 (temporary code here)
  4510                              <1> 	;
  4511                              <1> 	; INPUT ->
  4512                              <1> 	; 	ESI = Logical disk description table address
  4513                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4514                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4515                              <1> 	; 	ECX = Sector count
  4516                              <1> 	;
  4517                              <1> 	;
  4518                              <1> ;	retn
  4519                              <1> 
  4520                              <1> ; 24/12/2021
  4521                              <1> ; ('logical_disk_write' procedure call is disabled)
  4522                              <1> 
  4523                              <1> ;logical_disk_write:
  4524                              <1> 	; 20/07/2015
  4525                              <1> 	; 09/03/2015 (temporary code here)
  4526                              <1> 	;
  4527                              <1> 	; INPUT ->
  4528                              <1> 	; 	ESI = Logical disk description table address
  4529                              <1> 	; 	EBX = Memory page (buffer) address (physical!)
  4530                              <1> 	; 	EAX = Sector adress (offset address, logical sector number)
  4531                              <1> 	; 	ECX = Sector count
  4532                              <1> 	;
  4533                              <1> ;	retn
  4534                              <1> 
  4535                              <1> get_physical_addr:
  4536                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4537                              <1> 	; 19/04/2020 - Retro UNIX 386 v2
  4538                              <1> 	; 18/10/2015
  4539                              <1> 	; 29/07/2015
  4540                              <1> 	; 20/07/2015
  4541                              <1> 	; 04/06/2015
  4542                              <1> 	; 20/05/2015
  4543                              <1> 	; 28/04/2015
  4544                              <1> 	; 18/04/2015
  4545                              <1> 	; Get physical address
  4546                              <1> 	;     (allocates a new page for user if it is not present)
  4547                              <1> 	;	
  4548                              <1> 	; (This subroutine is needed for mapping user's virtual 
  4549                              <1> 	; (buffer) address to physical address (of the buffer).)
  4550                              <1> 	; ('sys write', 'sys read' system calls...)
  4551                              <1> 	;
  4552                              <1> 	; INPUT ->
  4553                              <1> 	;	EBX = virtual address
  4554                              <1> 	;	u.pgdir = page directory (physical) address
  4555                              <1> 	;
  4556                              <1> 	; OUTPUT ->
  4557                              <1> 	;	EAX = physical address 
  4558                              <1> 	;	EBX = linear address	
  4559                              <1> 	;	EDX = physical address of the page frame
  4560                              <1> 	;	      (with attribute bits)
  4561                              <1> 	;	ECX = byte count within the page frame
  4562                              <1> 	;
  4563                              <1> 	; Modified Registers -> EAX, EBX, ECX, EDX
  4564                              <1> 	;
  4565                              <1> 
  4566                              <1> 	; 19/04/2020 - Retro UNIX386 v2
  4567 000031A2 A1[F16E0000]        <1> 	mov	eax, [u.pgdir]
  4568                              <1> 
  4569                              <1> ifs_get_physical_addr: ; 19/04/2020 - Retro UNIX 386 v2
  4570                              <1> 	
  4571 000031A7 81C300004000        <1> 	add	ebx, CORE ; 18/10/2015
  4572                              <1> 	;
  4573                              <1> 	;mov	eax, [u.pgdir]
  4574 000031AD E816FDFFFF          <1> 	call	get_pte
  4575                              <1> 		; EDX = Page table entry address (if CF=0)
  4576                              <1> 	        ;       Page directory entry address (if CF=1)
  4577                              <1> 		;       (Bit 0 value is 0 if PT is not present)
  4578                              <1> 		; EAX = Page table entry value (page address)
  4579                              <1> 		;	CF = 1 -> PDE not present or invalid ? 
  4580 000031B2 731C                <1> 	jnc	short gpa_1
  4581                              <1> 	;
  4582 000031B4 E8FDFBFFFF          <1> 	call	allocate_page
  4583 000031B9 724B                <1> 	jc	short gpa_im_err  ; 'insufficient memory' error
  4584                              <1> gpa_0:
  4585 000031BB E867FCFFFF          <1> 	call 	clear_page
  4586                              <1> 	; EAX = Physical (base) address of the allocated (new) page
  4587 000031C0 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER ; 4+2+1 = 7
  4588                              <1> 			   ; lower 3 bits are used as U/S, R/W, P flags
  4589                              <1> 			   ; (user, writable, present page)	
  4590 000031C2 8902                <1> 	mov	[edx], eax ; Let's put the new page directory entry here !
  4591 000031C4 A1[F16E0000]        <1> 	mov	eax, [u.pgdir]	
  4592 000031C9 E8FAFCFFFF          <1> 	call	get_pte
  4593 000031CE 7236                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4594                              <1> gpa_1:
  4595                              <1> 	; EAX = PTE value, EDX = PTE address
  4596 000031D0 A801                <1> 	test 	al, PTE_A_PRESENT
  4597 000031D2 750A                <1> 	jnz	short gpa_3
  4598 000031D4 09C0                <1> 	or	eax, eax
  4599 000031D6 7420                <1> 	jz	short gpa_4  ; Allocate a new page
  4600                              <1> 
  4601                              <1> ; 24/12/2021
  4602                              <1> ; ('reload_page' procedure call is disabled)
  4603 000031D8 EB2C                <1> 	jmp	short gpa_im_err
  4604                              <1> 
  4605                              <1> 	; 20/07/2015
  4606                              <1> ;	push	ebp
  4607                              <1> ;	mov	ebp, ebx ; virtual (linear) address
  4608                              <1> ;	; reload swapped page
  4609                              <1> ;	call	reload_page ; 28/04/2015
  4610                              <1> ;	pop	ebp
  4611                              <1> ;	jc	short gpa_retn
  4612                              <1> gpa_2:
  4613                              <1> ; 24/12/2021
  4614                              <1> ; ('add_to_swap_queue' procedure call is disabled)
  4615                              <1> 
  4616                              <1> 	; 20/07/2015
  4617                              <1> 	; 20/05/2015
  4618                              <1> 	; add this page to swap queue
  4619                              <1> ;	push	eax 
  4620                              <1> ;	; EBX = Linear (CORE+virtual) address ; 20/02/2017 
  4621                              <1> ;	call 	add_to_swap_queue
  4622                              <1> ;	pop	eax
  4623                              <1> 		; PTE address in EDX
  4624                              <1> 		; virtual address in EBX
  4625                              <1> 	; EAX = memory page address
  4626 000031DA 0C07                <1> 	or	al, PTE_A_PRESENT + PTE_A_USER + PTE_A_WRITE
  4627                              <1> 				  ; present flag, bit 0 = 1
  4628                              <1> 				  ; user flag, bit 2 = 1	
  4629                              <1> 				  ; writable flag, bit 1 = 1
  4630 000031DC 8902                <1> 	mov	[edx], eax  ; Update PTE value
  4631                              <1> gpa_3:
  4632                              <1> 	; 18/10/2015
  4633 000031DE 89D9                <1> 	mov	ecx, ebx
  4634 000031E0 81E1FF0F0000        <1> 	and	ecx, PAGE_OFF
  4635 000031E6 89C2                <1> 	mov 	edx, eax
  4636 000031E8 662500F0            <1> 	and	ax, PTE_A_CLEAR
  4637 000031EC 01C8                <1> 	add	eax, ecx
  4638 000031EE F7D9                <1> 	neg	ecx ; 1 -> -1 (0FFFFFFFFh), 4095 (0FFFh) -> -4095
  4639 000031F0 81C100100000        <1> 	add	ecx, PAGE_SIZE
  4640 000031F6 F8                  <1> 	clc
  4641                              <1> gpa_retn:
  4642 000031F7 C3                  <1> 	retn	
  4643                              <1> gpa_4:	
  4644 000031F8 E8B9FBFFFF          <1> 	call	allocate_page
  4645 000031FD 7207                <1> 	jc	short gpa_im_err ; 'insufficient memory' error
  4646 000031FF E823FCFFFF          <1> 	call	clear_page
  4647 00003204 EBD4                <1> 	jmp	short gpa_2
  4648                              <1> 
  4649                              <1> gpa_im_err:	
  4650 00003206 B804000000          <1> 	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4651                              <1> 				  ; Major error = 0 (No protection fault)	
  4652 0000320B C3                  <1> 	retn
  4653                              <1> 
  4654                              <1> ; 24/12/2021
  4655                              <1> ; ('reload_page' procedure call is disabled)
  4656                              <1> 
  4657                              <1> ;reload_page:
  4658                              <1> 	; 20/07/2015
  4659                              <1> 	; 28/04/2015 (Retro UNIX 386 v1 - beginning)
  4660                              <1> 	;
  4661                              <1> 	; Reload (Restore) swapped page at memory
  4662                              <1> 	;
  4663                              <1> 	; INPUT -> 
  4664                              <1> 	;	EBP = Virtual (linear) memory address
  4665                              <1> 	;	EAX = PTE value (swap disk sector address)
  4666                              <1> 	;	(Swap disk sector address = bit 1 to bit 31 of EAX)	
  4667                              <1> 	; OUTPUT ->
  4668                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS OF RELOADED PAGE
  4669                              <1> 	;
  4670                              <1> 	;	CF = 1 and EAX = error code
  4671                              <1> 	;
  4672                              <1> 	; Modified Registers -> none (except EAX)
  4673                              <1> 	;
  4674                              <1> ;	shr	eax, 1   ; Convert PTE value to swap disk address 
  4675                              <1> ;	push	ebx      ;
  4676                              <1> ;	mov	ebx, eax ; Swap disk (offset) address	
  4677                              <1> ;	call	allocate_page
  4678                              <1> ;	jc	short rlp_im_err
  4679                              <1> ;	xchg 	eax, ebx	
  4680                              <1> ;	; EBX = Physical memory (page) address
  4681                              <1> ;	; EAX = Swap disk (offset) address
  4682                              <1> ;	; EBP = Virtual (linear) memory address
  4683                              <1> ;	call	swap_in
  4684                              <1> ;	jc	short rlp_swp_err  ; (swap disk/file read error)
  4685                              <1> ;	mov	eax, ebx	
  4686                              <1> ;rlp_retn:
  4687                              <1> ;	pop	ebx
  4688                              <1> ;	retn
  4689                              <1> ;	
  4690                              <1> ;rlp_im_err:	
  4691                              <1> ;	mov	eax, ERR_MINOR_IM ; Insufficient memory (minor) error!
  4692                              <1> ;				  ; Major error = 0 (No protection fault)	
  4693                              <1> ;	jmp	short rlp_retn
  4694                              <1> ;
  4695                              <1> ;rlp_swp_err:
  4696                              <1> ;	mov 	eax, SWP_DISK_READ_ERR ; Swap disk read error !
  4697                              <1> ;	jmp	short rlp_retn
  4698                              <1> 
  4699                              <1> copy_page_dir:
  4700                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4701                              <1> 	; 19/09/2015
  4702                              <1> 	; temporary - 07/09/2015
  4703                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4704                              <1> 	;
  4705                              <1> 	; INPUT -> 
  4706                              <1> 	;	[u.pgdir] = PHYSICAL (real/flat) ADDRESS of the parent's
  4707                              <1> 	;		    page directory.
  4708                              <1> 	; OUTPUT ->
  4709                              <1> 	;	EAX =  PHYSICAL (real/flat) ADDRESS of the child's
  4710                              <1> 	;	       page directory.
  4711                              <1> 	;	(New page directory with new page table entries.)
  4712                              <1> 	;	(New page tables with read only copies of the parent's
  4713                              <1> 	;	pages.)
  4714                              <1> 	;	EAX = 0 -> Error (CF = 1)
  4715                              <1> 	;
  4716                              <1> 	; Modified Registers -> none (except EAX)
  4717                              <1> 	;
  4718 0000320C E8A5FBFFFF          <1> 	call	allocate_page
  4719 00003211 723E                <1> 	jc	short cpd_err
  4720                              <1> 	;
  4721 00003213 55                  <1> 	push	ebp ; 20/07/2015
  4722 00003214 56                  <1> 	push	esi
  4723 00003215 57                  <1> 	push	edi
  4724 00003216 53                  <1> 	push	ebx
  4725 00003217 51                  <1> 	push	ecx
  4726 00003218 8B35[F16E0000]      <1> 	mov	esi, [u.pgdir]
  4727 0000321E 89C7                <1> 	mov	edi, eax
  4728 00003220 50                  <1> 	push	eax ; save child's page directory address
  4729                              <1> 	; copy PDE 0 from the parent's page dir to the child's page dir
  4730                              <1> 	; (use same system space for all user page tables) 
  4731 00003221 A5                  <1> 	movsd
  4732 00003222 BD00004000          <1> 	mov	ebp, 1024*4096 ; pass the 1st 4MB (system space)
  4733 00003227 B9FF030000          <1> 	mov	ecx, (PAGE_SIZE / 4) - 1 ; 1023
  4734                              <1> cpd_0:	
  4735 0000322C AD                  <1> 	lodsd
  4736                              <1> 	;or	eax, eax
  4737                              <1>         ;jnz	short cpd_1
  4738 0000322D A801                <1> 	test	al, PDE_A_PRESENT ;  bit 0 =  1
  4739 0000322F 7508                <1> 	jnz	short cpd_1
  4740                              <1>  	; (virtual address at the end of the page table)	
  4741 00003231 81C500004000        <1> 	add	ebp, 1024*4096 ; page size * PTE count
  4742 00003237 EB0F                <1> 	jmp	short cpd_2
  4743                              <1> cpd_1:	
  4744 00003239 662500F0            <1> 	and	ax, PDE_A_CLEAR ; 0F000h ; clear attribute bits
  4745 0000323D 89C3                <1> 	mov	ebx, eax
  4746                              <1> 	; EBX = Parent's page table address
  4747 0000323F E81F000000          <1> 	call	copy_page_table
  4748 00003244 720C                <1> 	jc	short cpd_p_err
  4749                              <1> 	; EAX = Child's page table address
  4750 00003246 0C07                <1> 	or	al, PDE_A_PRESENT + PDE_A_WRITE + PDE_A_USER
  4751                              <1> 			 ; set bit 0, bit 1 and bit 2 to 1
  4752                              <1> 			 ; (present, writable, user)
  4753                              <1> cpd_2:
  4754 00003248 AB                  <1> 	stosd
  4755 00003249 E2E1                <1> 	loop	cpd_0
  4756                              <1> 	;
  4757 0000324B 58                  <1> 	pop	eax  ; restore child's page directory address
  4758                              <1> cpd_3:
  4759 0000324C 59                  <1> 	pop	ecx
  4760 0000324D 5B                  <1> 	pop	ebx
  4761 0000324E 5F                  <1> 	pop	edi
  4762 0000324F 5E                  <1> 	pop	esi
  4763 00003250 5D                  <1> 	pop	ebp
  4764                              <1> cpd_err:
  4765 00003251 C3                  <1> 	retn
  4766                              <1> cpd_p_err:
  4767                              <1> 	; release the allocated pages missing (recover free space)
  4768 00003252 58                  <1> 	pop	eax  ; the new page directory address (physical)
  4769 00003253 8B1D[F16E0000]      <1> 	mov	ebx, [u.pgdir] ; parent's page directory address 
  4770 00003259 E888FCFFFF          <1> 	call 	deallocate_page_dir
  4771 0000325E 29C0                <1> 	sub	eax, eax ; 0
  4772 00003260 F9                  <1> 	stc
  4773 00003261 EBE9                <1> 	jmp	short cpd_3	
  4774                              <1> 
  4775                              <1> copy_page_table:
  4776                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4777                              <1> 	; 19/09/2015
  4778                              <1> 	; temporary - 07/09/2015
  4779                              <1> 	; 07/09/2015 (Retro UNIX 386 v1 - beginning)
  4780                              <1> 	;
  4781                              <1> 	; INPUT -> 
  4782                              <1> 	;	EBX = PHYSICAL (real/flat) ADDRESS of the parent's page table.
  4783                              <1> 	;	EBP = page table entry index (from 'copy_page_dir')
  4784                              <1> 	; OUTPUT ->
  4785                              <1> 	;	EAX = PHYSICAL (real/flat) ADDRESS of the child's page table.
  4786                              <1> 	;	EBP = (recent) page table index (for 'add_to_swap_queue')	
  4787                              <1> 	;	CF = 1 -> error 
  4788                              <1> 	;
  4789                              <1> 	; Modified Registers -> EBP (except EAX)
  4790                              <1> 	;
  4791 00003263 E84EFBFFFF          <1> 	call	allocate_page
  4792 00003268 7244                <1> 	jc	short cpt_err
  4793                              <1> 	;
  4794 0000326A 50                  <1> 	push	eax ; *
  4795                              <1> 	;push 	ebx
  4796 0000326B 56                  <1> 	push	esi
  4797 0000326C 57                  <1> 	push	edi
  4798 0000326D 52                  <1> 	push	edx
  4799 0000326E 51                  <1> 	push	ecx
  4800                              <1> 	;
  4801 0000326F 89DE                <1> 	mov	esi, ebx
  4802 00003271 89C7                <1> 	mov	edi, eax
  4803 00003273 89C2                <1> 	mov	edx, eax
  4804 00003275 81C200100000        <1> 	add	edx, PAGE_SIZE 	
  4805                              <1> cpt_0:
  4806 0000327B AD                  <1> 	lodsd
  4807 0000327C A801                <1> 	test	al, PTE_A_PRESENT ;  bit 0 = 1
  4808                              <1> 	;jnz	short cpt_1 (*)
  4809                              <1> 	; 24/12/2021
  4810                              <1> 	;and	eax, eax (*)
  4811 0000327E 741E                <1> 	jz	short cpt_2  ; 24/12/2021
  4812                              <1> 	
  4813                              <1> ; 24/12/2021
  4814                              <1> ; ('reload_page' procedure call is disabled)
  4815                              <1> ;
  4816                              <1> ;	; ebp = virtual (linear) address of the memory page
  4817                              <1> ;	call	reload_page ; 28/04/2015
  4818                              <1> ;	jc	short cpt_p_err
  4819                              <1> cpt_1:
  4820 00003280 662500F0            <1> 	and	ax, PTE_A_CLEAR ; 0F000h ; clear attribute bits
  4821 00003284 89C1                <1> 	mov	ecx, eax
  4822                              <1> 	; Allocate a new page for the child process
  4823 00003286 E82BFBFFFF          <1> 	call	allocate_page
  4824 0000328B 721C                <1> 	jc	short cpt_p_err
  4825 0000328D 57                  <1> 	push	edi
  4826 0000328E 56                  <1> 	push	esi
  4827 0000328F 89CE                <1> 	mov	esi, ecx
  4828 00003291 89C7                <1> 	mov	edi, eax
  4829 00003293 B900040000          <1> 	mov	ecx, PAGE_SIZE/4
  4830 00003298 F3A5                <1> 	rep	movsd	; copy page (4096 bytes)
  4831 0000329A 5E                  <1> 	pop	esi
  4832 0000329B 5F                  <1> 	pop	edi
  4833                              <1> 	; 
  4834                              <1> ; 24/12/2021
  4835                              <1> ; ('add_to_swap_queue' procedure call is disabled)	
  4836                              <1> ;
  4837                              <1> ;	push	ebx
  4838                              <1> ;	push	eax
  4839                              <1> ;	mov	ebx, ebp
  4840                              <1> ;	; ebx = virtual address of the memory page
  4841                              <1> ;	call	add_to_swap_queue
  4842                              <1> ;	pop	eax
  4843                              <1> ;	pop	ebx
  4844                              <1> 	;
  4845                              <1> 	;or	ax, PTE_A_USER+PTE_A_PRESENT 
  4846 0000329C 0C07                <1> 	or	al, PTE_A_USER+PTE_A_WRITE+PTE_A_PRESENT 
  4847                              <1> cpt_2:
  4848 0000329E AB                  <1> 	stosd  ; EDI points to child's PTE  	 
  4849                              <1> 	;
  4850 0000329F 81C500100000        <1> 	add	ebp, 4096 ; 20/07/2015 (next page)
  4851                              <1> 	;
  4852 000032A5 39D7                <1> 	cmp	edi, edx
  4853 000032A7 72D2                <1> 	jb	short cpt_0
  4854                              <1> cpt_p_err:
  4855 000032A9 59                  <1> 	pop	ecx
  4856 000032AA 5A                  <1> 	pop	edx
  4857 000032AB 5F                  <1> 	pop	edi
  4858 000032AC 5E                  <1> 	pop	esi
  4859                              <1> 	;pop	ebx
  4860 000032AD 58                  <1> 	pop	eax ; *
  4861                              <1> cpt_err:
  4862 000032AE C3                  <1> 	retn
  4863                              <1> 
  4864                              <1> ; /// End Of MEMORY MANAGEMENT FUNCTIONS ///
  4865                              <1> 
  4866                              <1> ;; Data:
  4867                              <1> 
  4868                              <1> ; 09/03/2015
  4869                              <1> ;swpq_count: dw 0 ; count of pages on the swap que
  4870                              <1> ;swp_drv:    dd 0 ; logical drive description table address of the swap drive/disk
  4871                              <1> ;swpd_size:  dd 0 ; size of swap drive/disk (volume) in sectors (512 bytes).
  4872                              <1> ;swpd_free:  dd 0 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  4873                              <1> ;swpd_next:  dd 0 ; next free page block
  4874                              <1> ;swpd_last:  dd 0 ; last swap page block		 		
  2094                                  %include 'sysdefs.inc' ; 09/03/2015
  2095                              <1> ; Retro UNIX 386 v1.1 Kernel - SYSDEFS.INC
  2096                              <1> ; Last Modification: 08/02//2022
  2097                              <1> ;
  2098                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2099                              <1> ; (Modified from 
  2100                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2101                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2102                              <1> ; 	UNIX.ASM (MASM 6.11) --> SYSDEFS.INC (NASM 2.11)
  2103                              <1> ; ----------------------------------------------------------------------------
  2104                              <1> ;
  2105                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2106                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2107                              <1> ; <Bell Laboratories (17/3/1972)>
  2108                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2109                              <1> ;
  2110                              <1> ; ****************************************************************************
  2111                              <1> 
  2112                              <1> nproc 	equ	16  ; number of processes
  2113                              <1> nfiles 	equ	50
  2114                              <1> ntty	equ     8   ; 8+1 -> 8 (10/05/2013)
  2115                              <1> nbuf	equ	6   ; number of buffers (04/02/2016)
  2116                              <1> 
  2117                              <1> ;csgmnt	equ	2000h	; 26/05/2013 (segment of process 1)
  2118                              <1> ;core	equ 	0  	    ; 19/04/2013	
  2119                              <1> ;ecore	equ	32768 - 64  ; 04/06/2013 (24/05/2013)
  2120                              <1> 	; (if total size of argument list and arguments is 128 bytes)
  2121                              <1> 	; maximum executable file size = 32768-(64+40+128-6) = 32530 bytes
  2122                              <1> 	; maximum stack size = 40 bytes (+6 bytes for 'IRET' at 32570)	
  2123                              <1> 	; initial value of user's stack pointer = 32768-64-128-2 = 32574
  2124                              <1> 	; 	(sp=32768-args_space-2 at the beginning of execution)
  2125                              <1> 	; argument list offset = 32768-64-128 = 32576 (if it is 128 bytes)
  2126                              <1> 	; 'u' structure offset (for the '/core' dump file) = 32704
  2127                              <1> 	; '/core' dump file size = 32768 bytes
  2128                              <1>  
  2129                              <1> ; 08/03/2014 
  2130                              <1> ;sdsegmnt equ	6C0h  ; 256*16 bytes (swap data segment size for 16 processes)		 	 
  2131                              <1> ; 19/04/2013 Retro UNIX 8086 v1 feaure only !
  2132                              <1> ;;sdsegmnt equ 	740h  ; swap data segment (for user structures and registers)
  2133                              <1> 
  2134                              <1> ; 30/08/2013
  2135                              <1> time_count equ 4 ; 10 --> 4 01/02/2014
  2136                              <1> 
  2137                              <1> ; 05/02/2014
  2138                              <1> ; process status
  2139                              <1> ;SFREE 	equ 0
  2140                              <1> ;SRUN	equ 1
  2141                              <1> ;SWAIT	equ 2
  2142                              <1> ;SZOMB	equ 3
  2143                              <1> ;SSLEEP	equ 4 ; Retro UNIX 8086 V1 extension (for sleep and wakeup)
  2144                              <1> 
  2145                              <1> ; 09/03/2015
  2146                              <1> userdata equ 80000h ; user structure data address for current user ; temporary
  2147                              <1> swap_queue equ 90000h - 2000h ; swap queue address ; temporary
  2148                              <1> swap_alloc_table equ 0D0000h  ;  swap allocation table address ; temporary
  2149                              <1> 
  2150                              <1> ; 17/09/2015
  2151                              <1> ESPACE equ 48 ; [u.usp] (at 'sysent') - [u.sp] value for error return
  2152                              <1> 
  2153                              <1> ; 21/09/2015 (36) 
  2154                              <1> ; 01/07/2015 (35)
  2155                              <1> ; 14/07/2013 (0-34)
  2156                              <1> ; UNIX v1 system calls
  2157                              <1> _rele 	equ 0
  2158                              <1> _exit 	equ 1
  2159                              <1> _fork 	equ 2
  2160                              <1> _read 	equ 3
  2161                              <1> _write	equ 4
  2162                              <1> _open	equ 5
  2163                              <1> _close 	equ 6
  2164                              <1> _wait 	equ 7
  2165                              <1> _creat 	equ 8
  2166                              <1> _link 	equ 9
  2167                              <1> _unlink	equ 10
  2168                              <1> _exec	equ 11
  2169                              <1> _chdir	equ 12
  2170                              <1> _time 	equ 13
  2171                              <1> _mkdir 	equ 14
  2172                              <1> _chmod	equ 15
  2173                              <1> _chown	equ 16
  2174                              <1> _break	equ 17
  2175                              <1> _stat	equ 18
  2176                              <1> _seek	equ 19
  2177                              <1> _tell 	equ 20
  2178                              <1> _mount	equ 21
  2179                              <1> _umount	equ 22
  2180                              <1> _setuid	equ 23
  2181                              <1> _getuid	equ 24
  2182                              <1> _stime	equ 25
  2183                              <1> _quit	equ 26	
  2184                              <1> _intr	equ 27
  2185                              <1> _fstat	equ 28
  2186                              <1> _emt 	equ 29
  2187                              <1> _mdate 	equ 30
  2188                              <1> _stty 	equ 31
  2189                              <1> _gtty	equ 32
  2190                              <1> _ilgins	equ 33
  2191                              <1> _sleep	equ 34 ; Retro UNIX 8086 v1 feature only !
  2192                              <1> _msg	equ 35 ; Retro UNIX 386 v1 feature only !
  2193                              <1> _geterr	equ 36 ; Retro UNIX 386 v1 feature only !
  2194                              <1> 
  2195                              <1> %macro sys 1-4
  2196                              <1>     ; 13/04/2015
  2197                              <1>     ; Retro UNIX 386 v1 system call.		
  2198                              <1>     mov eax, %1
  2199                              <1>     %if %0 >= 2   
  2200                              <1>         mov ebx, %2
  2201                              <1>         %if %0 >= 3    
  2202                              <1>             mov ecx, %3
  2203                              <1>             %if %0 = 4
  2204                              <1>                mov edx, %4   
  2205                              <1>             %endif
  2206                              <1>         %endif
  2207                              <1>     %endif
  2208                              <1>     int 30h	   
  2209                              <1> %endmacro
  2210                              <1> 
  2211                              <1> ; 13/05/2015 - ERROR CODES
  2212                              <1> ERR_FILE_NOT_OPEN  equ 10 ; 'file not open !' error
  2213                              <1> ERR_FILE_ACCESS    equ 11 ; 'permission denied !' error
  2214                              <1> ; 14/05/2015
  2215                              <1> ERR_DIR_ACCESS     equ 11 ; 'permission denied !' error
  2216                              <1> ERR_FILE_NOT_FOUND equ 12 ; 'file not found !' error
  2217                              <1> ERR_TOO_MANY_FILES equ 13 ; 'too many open files !' error
  2218                              <1> ERR_DIR_EXISTS     equ 14 ; 'directory already exists !' error 	
  2219                              <1> ; 16/05/2015		
  2220                              <1> ERR_DRV_NOT_RDY    equ 15 ; 'drive not ready !' error
  2221                              <1> ; 18/05/2015
  2222                              <1> ERR_DEV_NOT_RDY    equ 15 ; 'device not ready !' error
  2223                              <1> ERR_DEV_ACCESS     equ 11 ; 'permission denied !' error 
  2224                              <1> ERR_DEV_NOT_OPEN   equ 10 ; 'device not open !' error	
  2225                              <1> ; 07/06/2015
  2226                              <1> ERR_FILE_EOF	   equ 16 ; 'end of file !' error
  2227                              <1> ERR_DEV_VOL_SIZE   equ 16 ; 'out of volume' error
  2228                              <1> ; 09/06/2015
  2229                              <1> ERR_DRV_READ	   equ 17 ; 'disk read error !'
  2230                              <1> ERR_DRV_WRITE	   equ 18 ; 'disk write error !'
  2231                              <1> ; 16/06/2015
  2232                              <1> ERR_NOT_DIR	   equ 19 ; 'not a (valid) directory !' error
  2233                              <1> ERR_FILE_SIZE	   equ 20 ; 'file size error !'	
  2234                              <1> ; 22/06/2015
  2235                              <1> ERR_NOT_SUPERUSER  equ 11 ; 'permission denied !' error
  2236                              <1> ERR_NOT_OWNER      equ 11 ; 'permission denied !' error
  2237                              <1> ERR_NOT_FILE       equ 11 ; 'permission denied !' error	
  2238                              <1> ; 23/06/2015
  2239                              <1> ERR_FILE_EXISTS    equ 14 ; 'file already exists !' error
  2240                              <1> ERR_DRV_NOT_SAME   equ 21 ; 'not same drive !' error
  2241                              <1> ERR_DIR_NOT_FOUND  equ 12 ; 'directory not found !' error
  2242                              <1> ERR_NOT_EXECUTABLE equ 22 ; 'not executable file !' error
  2243                              <1> ; 27/06/2015
  2244                              <1> ERR_INV_PARAMETER  equ 23 ; 'invalid parameter !' error
  2245                              <1> ERR_INV_DEV_NAME   equ 24 ; 'invalid device name !' error
  2246                              <1> ; 29/06/2015
  2247                              <1> ERR_TIME_OUT	   equ 25 ; 'time out !' error			
  2248                              <1> ERR_DEV_NOT_RESP   equ 25 ; 'device not responding !' error
  2249                              <1> ; 08/02/2022 
  2250                              <1> ; (error numbers from TRDOS 386 v2.0 'sysdefs.s')
  2251                              <1> ; 10/10/2016
  2252                              <1> ERR_INV_FILE_NAME  equ 26 ; 'invalid file name !' error
  2253                              <1> ; 18/05/2016
  2254                              <1> ERR_MISC	   equ 27 ; miscellaneous/other errors
  2255                              <1> ; 15/10/2016
  2256                              <1> ERR_INV_FORMAT	   equ 28 ; 'invalid format !' error
  2257                              <1> ERR_INV_DATA	   equ 29 ; 'invalid data !' error
  2258                              <1> ; 16/10/2016
  2259                              <1> ERR_DISK_WRITE	   equ 30 ; 'disk write protected !'
  2260                              <1> ; 08/02/2022
  2261                              <1> ERR_INV_FS	   equ 28  ;'invalid fs/superblock !' error
  2262                              <1> 
  2263                              <1> ; 26/08/2015
  2264                              <1> ; 24/07/2015
  2265                              <1> ; 24/06/2015
  2266                              <1> MAX_ARG_LEN	   equ 256 ; max. length of sys exec arguments
  2267                              <1> ; 01/07/2015
  2268                              <1> MAX_MSG_LEN	   equ 255 ; max. msg length for 'sysmsg'
  2269                              <1> ; 24/12/2021
  2270                              <1> ERR_INV_FUNC	   equ 1  ; 'invalid system call !' error	 					 		
  2095                                  %include 'u0.s'        ; 15/03/2015
  2096                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS0.INC
  2097                              <1> ; Last Modification: 26/02/2022
  2098                              <1> ; ----------------------------------------------------------------------------
  2099                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2100                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2101                              <1> ;
  2102                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2103                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2104                              <1> ; <Bell Laboratories (17/3/1972)>
  2105                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2106                              <1> ;
  2107                              <1> ; Retro UNIX 8086 v1 - U0.ASM (28/07/2014) //// UNIX v1 -> u0.s
  2108                              <1> ;
  2109                              <1> ; ****************************************************************************
  2110                              <1> 
  2111                              <1> sys_init:
  2112                              <1> 	; 26/02/2022
  2113                              <1> 	; 08/01/2022
  2114                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2115                              <1> 	; 18/10/2015
  2116                              <1> 	; 28/08/2015
  2117                              <1> 	; 24/08/2015
  2118                              <1> 	; 14/08/2015
  2119                              <1> 	; 24/07/2015 
  2120                              <1> 	; 02/07/2015
  2121                              <1> 	; 01/07/2015
  2122                              <1> 	; 23/06/2015
  2123                              <1> 	; 15/04/2015
  2124                              <1> 	; 13/03/2015
  2125                              <1> 	; 11/03/2015 (Retro UNIX 386 v1 - Beginning)
  2126                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2127                              <1> 	;
  2128                              <1> 	;call	ldrv_init ; Logical drive description tables initialization
  2129                              <1> 	;
  2130                              <1> 	; 14/02/2014
  2131                              <1> 	; 14/07/2013
  2132                              <1> 	;;mov	ax, 41
  2133                              <1> 	; 24/12/2021
  2134                              <1> 	;xor	eax, eax
  2135                              <1> 	;mov	al, 41
  2136                              <1> 	;mov	[rootdir], ax
  2137                              <1> 	;mov	[u.cdir], ax
  2138                              <1> 	;;and	al, 1 ; 15/04/2015
  2139                              <1> 	;inc	al  ; ax = 1
  2140 000032AF B001                <1> 	mov	al, 1
  2141 000032B1 A2[E76E0000]        <1> 	mov	[u.uno], al
  2142                              <1> 	;mov	[mpid], ax
  2143                              <1> 	;mov	[p.pid], ax
  2144 000032B6 A2[866E0000]        <1> 	mov	[mpid], al
  2145 000032BB A2[B86B0000]        <1> 	mov	[p.pid], al	
  2146 000032C0 A2[186C0000]        <1> 	mov	[p.stat], al ; SRUN, 05/02/2014
  2147                              <1> 	; 24/12/2021
  2148 000032C5 B029                <1> 	mov	al, 41
  2149                              <1> 	;mov	[rootdir], ax
  2150                              <1> 	;mov	[u.cdir], ax
  2151 000032C7 A2[886E0000]        <1> 	mov	[rootdir], al
  2152 000032CC A2[9C6E0000]        <1> 	mov	[u.cdir], al
  2153                              <1> 	;
  2154 000032D1 B004                <1> 	mov	al, time_count ; 30/08/2013
  2155 000032D3 A2[DA6E0000]        <1> 	mov	[u.quant], al ; 14/07/2013
  2156                              <1> 	; 02/07/2015
  2157 000032D8 A1[D86A0000]        <1> 	mov	eax, [k_page_dir]
  2158                              <1> 	;sub	eax, eax
  2159 000032DD A3[F16E0000]        <1> 	mov	[u.pgdir], eax ; reset
  2160                              <1> 	; 18/10/2015
  2161                              <1> 	;mov	[u.ppgdir], eax ; 0
  2162                              <1> 	; 26/02/2022
  2163                              <1>  	;call	epoch
  2164                              <1> 	;mov	[s.time], eax ; 13/03/2015
  2165                              <1> 	; 17/07/2013
  2166 000032E2 E88F060000          <1> 	call 	bf_init ; buffer initialization
  2167                              <1> 	; 26/02/2022
  2168                              <1> 	; (save sysinit time on sb0)
  2169 000032E7 E829030000          <1> 	call	epoch
  2170 000032EC A3[E47C0000]        <1> 	mov	[s.time], eax ; 13/03/2015
  2171                              <1> 	; 23/06/2015
  2172 000032F1 E8C0FAFFFF          <1> 	call	allocate_page
  2173                              <1> 	;;jc	error
  2174                              <1> 	;jc	panic   ; jc short panic (01/07/2015)
  2175                              <1> 	; 24/12/2021
  2176 000032F6 7305                <1> 	jnc	short sysinit_1
  2177 000032F8 E989000000          <1> 	jmp	panic
  2178                              <1> sysinit_1:
  2179 000032FD A3[E86E0000]        <1> 	mov	[u.upage], eax ; user structure page	
  2180 00003302 A3[286C0000]        <1> 	mov	[p.upage], eax
  2181                              <1> 	;
  2182 00003307 E81BFBFFFF          <1> 	call	clear_page
  2183                              <1> 	;
  2184                              <1> 	; 14/08/2015
  2185 0000330C FA                  <1> 	cli
  2186                              <1> 	; 14/03/2015
  2187                              <1> 	; 17/01/2014
  2188 0000330D E8D0010000          <1> 	call	sp_init ; serial port initialization
  2189                              <1> 	; 14/08/2015
  2190 00003312 FB                  <1> 	sti
  2191                              <1> 	;
  2192                              <1> 	; 30/06/2015
  2193                              <1> 	;mov	esi, kernel_init_ok_msg
  2194                              <1> 	;call 	print_msg
  2195                              <1> 	;
  2196 00003313 30DB                <1> 	xor	bl, bl ; video page 0
  2197                              <1> vp_clr_nxt:  ; clear video pages (reset cursor positions)
  2198 00003315 E8500F0000          <1> 	call 	vp_clr  ; 17/07/2013
  2199 0000331A FEC3                <1> 	inc	bl
  2200 0000331C 80FB08              <1> 	cmp	bl, 8
  2201 0000331F 72F4                <1> 	jb	short vp_clr_nxt
  2202                              <1> 	;
  2203                              <1> 	; 24/07/2015
  2204                              <1> 	;push    KDATA
  2205                              <1>         ;push    esp
  2206                              <1> 	;mov	[tss.esp0], esp
  2207                              <1>         ;mov     word [tss.ss0], KDATA
  2208                              <1> 	;
  2209                              <1> 	; 08/01/2022
  2210                              <1> 	; 24/08/2015
  2211                              <1> 	;; temporary (01/07/2015)
  2212                              <1> 	;mov	byte [u.quant], time_count ; 4 
  2213                              <1> 			       ; it is not needed here !
  2214                              <1> 	;;inc	byte [u.kcall] ; 'the caller is kernel' sign
  2215 00003321 FE0D[8F6E0000]      <1> 	dec 	byte [sysflg] ; FFh = ready for system call
  2216                              <1> 			      ; 0 = executing a system call
  2217                              <1> 	;;sys 	_msg, kernel_init_ok_msg, 255, 0
  2218                              <1> 	;
  2219                              <1> 	;;; 06/08/2015
  2220                              <1> 	;;;call	getch ; wait for a key stroke
  2221                              <1> 	;;mov 	ecx, 0FFFFFFFh	
  2222                              <1> ;;sys_init_msg_wait:
  2223                              <1> ;;	push 	ecx
  2224                              <1> ;;	mov	al, 1
  2225                              <1> ;;	mov 	ah, [ptty] ; active (current) video page
  2226                              <1> ;;	call	getc_n
  2227                              <1> ;;	pop	ecx
  2228                              <1> ;;	jnz	short sys_init_msg_ok
  2229                              <1> ;;	loop	sys_init_msg_wait
  2230                              <1> 	;
  2231                              <1> ;;sys_init_msg_ok:
  2232                              <1> 	; 28/08/2015 (initial settings for the 1st 'rswap')
  2233 00003327 6A10                <1> 	push	KDATA ; ss
  2234 00003329 54                  <1> 	push	esp
  2235 0000332A 9C                  <1> 	pushfd
  2236 0000332B 6A08                <1> 	push	KCODE ; cs
  2237 0000332D 68[5A330000]        <1> 	push	init_exec ; eip
  2238 00003332 8925[906E0000]      <1> 	mov	[u.sp], esp
  2239 00003338 1E                  <1> 	push	ds
  2240 00003339 06                  <1> 	push	es
  2241 0000333A 0FA0                <1> 	push	fs
  2242 0000333C 0FA8                <1> 	push	gs	
  2243 0000333E 60                  <1> 	pushad
  2244 0000333F 8925[946E0000]      <1> 	mov	[u.usp], esp
  2245 00003345 E8671B0000          <1> 	call	wswap ; save current user (u) structure, user registers
  2246                              <1> 		      ; and interrupt return components (for IRET)
  2247 0000334A 61                  <1> 	popad
  2248 0000334B 6658                <1> 	pop	ax ; gs
  2249 0000334D 6658                <1> 	pop	ax ; fs
  2250 0000334F 6658                <1> 	pop	ax ; es
  2251 00003351 6658                <1> 	pop	ax ; ds	
  2252 00003353 58                  <1> 	pop	eax ; eip (init_exec)
  2253 00003354 6658                <1> 	pop	ax ; cs (KCODE)
  2254 00003356 58                  <1> 	pop	eax ; E-FLAGS
  2255 00003357 58                  <1> 	pop	eax ; esp
  2256 00003358 6658                <1> 	pop	ax ; ss (KDATA)
  2257                              <1> 	;
  2258                              <1> 	; 08/01/2022 ([u.ppgdir] is zero already)
  2259                              <1> 	;xor	eax, eax ; 0
  2260                              <1> 	;mov	[u.ppgdir], eax ; reset (to zero) for '/etc/init'
  2261                              <1> 	;
  2262                              <1> 	; 02/07/2015
  2263                              <1> 	; [u.pgdir ] = [k_page_dir]
  2264                              <1> 	; [u.ppgdir] = 0 (page dir of the parent process)
  2265                              <1> 	;     (The caller is os kernel sign for 'sysexec')
  2266                              <1> init_exec:
  2267                              <1> 	; 13/03/2013
  2268                              <1> 	; 24/07/2013
  2269 0000335A BB[7C330000]        <1> 	mov	ebx, init_file
  2270 0000335F B9[74330000]        <1> 	mov	ecx, init_argp
  2271                              <1> 	; EBX contains 'etc/init' asciiz file name address  
  2272                              <1> 	; ECX contains address of argument list pointer
  2273                              <1> 	;
  2274                              <1> 	;dec 	byte [sysflg] ; FFh = ready for system call
  2275                              <1> 			      ; 0 = executing a system call
  2276                              <1> 	sys	_exec  ; execute file
  2196                              <2> 
  2197                              <2> 
  2198 00003364 B80B000000          <2>  mov eax, %1
  2199                              <2>  %if %0 >= 2
  2200                              <2>  mov ebx, %2
  2201                              <2>  %if %0 >= 3
  2202                              <2>  mov ecx, %3
  2203                              <2>  %if %0 = 4
  2204                              <2>  mov edx, %4
  2205                              <2>  %endif
  2206                              <2>  %endif
  2207                              <2>  %endif
  2208 00003369 CD30                <2>  int 30h
  2277 0000336B 7319                <1> 	jnc	short panic
  2278                              <1> 	;
  2279 0000336D BE[EC670000]        <1> 	mov	esi, etc_init_err_msg
  2280                              <1> 	; 08/01/2022
  2281                              <1> 	;call 	print_msg
  2282 00003372 EB17                <1> 	jmp	short key_to_reboot
  2283                              <1> 
  2284                              <1> ;align 4
  2285                              <1> init_argp:
  2286 00003374 [7C330000]00000000  <1> 	dd 	init_file, 0  ; 23/06/2015 (dw -> dd)
  2287                              <1> init_file:
  2288                              <1> 	; 24/08/2015
  2289 0000337C 2F6574632F696E6974- <1> 	db 	'/etc/init', 0
  2289 00003385 00                  <1>
  2290                              <1> panic:
  2291                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2292                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2293 00003386 BE[D1670000]        <1> 	mov 	esi, panic_msg
  2294                              <1> key_to_reboot: ; 08/01/2022 (Retro UNIX 386 v1.1)
  2295 0000338B E819000000          <1> 	call 	print_msg
  2296                              <1> ;key_to_reboot:
  2297                              <1> 	; 15/11/2015
  2298 00003390 E8D82B0000          <1> 	call 	getch 
  2299                              <1> 		; wait for a character from the current tty
  2300                              <1> 	;
  2301 00003395 B00A                <1> 	mov	al, 0Ah
  2302 00003397 8A1D[066B0000]      <1> 	mov	bl, [ptty] ; [active_page]
  2303 0000339D B407                <1> 	mov	ah, 07h ; Black background, 
  2304                              <1> 			; light gray forecolor
  2305 0000339F E822E0FFFF          <1> 	call 	write_tty
  2306 000033A4 E9BDDCFFFF          <1> 	jmp	cpu_reset 
  2307                              <1> 
  2308                              <1> print_msg:
  2309                              <1> 	; 01/07/2015
  2310                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2311                              <1> 	; 07/03/2014 (Retro UNIX 8086 v1)
  2312                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI, EDI)
  2313                              <1> 	;
  2314                              <1> 	;
  2315 000033A9 AC                  <1> 	lodsb
  2316                              <1> pmsg1:
  2317 000033AA 56                  <1> 	push 	esi
  2318 000033AB 0FB61D[066B0000]    <1> 	movzx	ebx, byte [ptty]
  2319 000033B2 B407                <1> 	mov	ah, 07h ; Black background, light gray forecolor
  2320 000033B4 E80DE0FFFF          <1> 	call 	write_tty
  2321 000033B9 5E                  <1> 	pop	esi
  2322 000033BA AC                  <1> 	lodsb
  2323 000033BB 20C0                <1> 	and 	al, al
  2324 000033BD 75EB                <1> 	jnz 	short pmsg1
  2325 000033BF C3                  <1> 	retn
  2326                              <1> 	
  2327                              <1> ctrlbrk:
  2328                              <1> 	; 04/02/2022
  2329                              <1> 	; 01/02/2022
  2330                              <1> 	; 12/11/2015
  2331                              <1> 	; 13/03/2015 (Retro UNIX 386 v1)
  2332                              <1> 	; 06/12/2013 (Retro UNIX 8086 v1)
  2333                              <1> 	;
  2334                              <1> 	; INT 1Bh (control+break) handler
  2335                              <1> 	;
  2336                              <1>       	; Retro Unix 8086 v1 feature only!
  2337                              <1>       	;
  2338 000033C0 66833D[DC6E0000]00  <1> 	cmp 	word [u.intr], 0
  2339 000033C8 764B                <1> 	jna 	short cbrk4
  2340                              <1> cbrk0:
  2341                              <1> 	; 12/11/2015
  2342                              <1> 	; 06/12/2013
  2343 000033CA 66833D[DE6E0000]00  <1> 	cmp 	word [u.quit], 0
  2344 000033D2 7441                <1> 	jz	short cbrk4
  2345                              <1> 	;
  2346                              <1> 	; 20/09/2013	
  2347                              <1> 	;push 	ax
  2348                              <1> 	; 01/02/2022
  2349 000033D4 50                  <1> 	push	eax
  2350                              <1> 
  2351                              <1> 	; 04/02/2022
  2352                              <1> 	; (repetitive ctrl+brk check) 
  2353 000033D5 66A1[DE6E0000]      <1> 	mov	ax, [u.quit]
  2354 000033DB 6640                <1> 	inc	ax ; 0FFFFh -> 0
  2355 000033DD 7435                <1> 	jz	short cbrk3
  2356                              <1> 
  2357                              <1> 	; 20/09/2013
  2358 000033DF A0[066B0000]        <1> 	mov	al, [ptty]
  2359                              <1> 	;
  2360                              <1> 	; 12/11/2015
  2361                              <1> 	;
  2362                              <1> 	; ctrl+break (EOT, CTRL+D) from serial port
  2363                              <1> 	; or ctrl+break from console (pseudo) tty
  2364                              <1> 	; (!redirection!)
  2365                              <1> 	;
  2366 000033E4 3C08                <1> 	cmp	al, 8 ; serial port tty nums > 7
  2367 000033E6 7211                <1>         jb      short cbrk1 ; console (pseudo) tty
  2368                              <1> 	;	
  2369                              <1> 	; Serial port interrupt handler sets [ptty]
  2370                              <1> 	; to the port's tty number (as temporary).
  2371                              <1> 	;
  2372                              <1> 	; If active process is using a stdin or 
  2373                              <1> 	; stdout redirection (by the shell),
  2374                              <1>         ; console tty keyboard must be available
  2375                              <1> 	; to terminate running process,
  2376                              <1> 	; in order to prevent a deadlock. 
  2377                              <1> 	;
  2378 000033E8 52                  <1> 	push	edx
  2379 000033E9 0FB615[E76E0000]    <1> 	movzx	edx, byte [u.uno]
  2380 000033F0 3A82[F76B0000]      <1> 	cmp     al, [edx+p.ttyc-1] ; console tty (rw)
  2381 000033F6 5A                  <1> 	pop	edx
  2382 000033F7 7412                <1> 	je	short cbrk2
  2383                              <1> cbrk1:
  2384 000033F9 FEC0                <1> 	inc 	al  ; [u.ttyp] : 1 based tty number
  2385                              <1> 	; 06/12/2013
  2386 000033FB 3A05[C86E0000]      <1> 	cmp	al, [u.ttyp] ; recent open tty (r)
  2387 00003401 7408                <1> 	je	short cbrk2	
  2388 00003403 3A05[C96E0000]      <1>         cmp     al, [u.ttyp+1] ; recent open tty (w)
  2389 00003409 7509                <1> 	jne	short cbrk3	
  2390                              <1> cbrk2:
  2391                              <1> 	;; 06/12/2013
  2392                              <1> 	;mov	ax, [u.quit]
  2393                              <1> 	;and	ax, ax
  2394                              <1> 	;jz	short cbrk3
  2395                              <1> 	;
  2396                              <1> 	;xor	ax, ax ; 0
  2397                              <1> 	;dec	ax
  2398                              <1> 	; 01/02/2022
  2399 0000340B 31C0                <1> 	xor	eax, eax ; 0
  2400 0000340D 48                  <1> 	dec	eax ; 0FFFFFFFFh
  2401                              <1> 	; 0FFFFh = 'ctrl+brk' keystroke
  2402 0000340E 66A3[DE6E0000]      <1> 	mov	[u.quit], ax
  2403                              <1> cbrk3:
  2404                              <1> 	;pop	ax
  2405                              <1> 	; 01/02/2022
  2406 00003414 58                  <1> 	pop	eax
  2407                              <1> cbrk4:
  2408 00003415 C3                  <1> 	retn
  2409                              <1> 
  2410                              <1> com2_int:
  2411                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2412                              <1> 	; 07/11/2015 
  2413                              <1> 	; 24/10/2015
  2414                              <1> 	; 23/10/2015
  2415                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2416                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2417                              <1> 	; < serial port 2 interrupt handler >
  2418                              <1> 	;
  2419 00003416 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2420                              <1> 	;;push	eax
  2421                              <1> 	; 08/01/2022
  2422 00003419 29C0                <1> 	sub	eax, eax
  2423 0000341B B009                <1> 	mov	al, 9
  2424                              <1> 	;mov	ax, 9
  2425 0000341D EB07                <1> 	jmp	short comm_int
  2426                              <1> com1_int:
  2427                              <1> 	; 07/11/2015
  2428                              <1> 	; 24/10/2015
  2429 0000341F 890424              <1> 	mov 	[esp], eax ; overwrite call return address
  2430                              <1> 	; 23/10/2015
  2431                              <1> 	;push	eax
  2432                              <1> 	; 08/01/2022
  2433 00003422 29C0                <1> 	sub	eax, eax
  2434 00003424 B008                <1> 	mov	al, 8
  2435                              <1> 	;mov	ax, 8
  2436                              <1> comm_int:
  2437                              <1> 	; 08/01/2022
  2438                              <1> 	; 20/11/2015
  2439                              <1> 	; 18/11/2015
  2440                              <1> 	; 17/11/2015
  2441                              <1> 	; 16/11/2015
  2442                              <1> 	; 09/11/2015
  2443                              <1> 	; 08/11/2015
  2444                              <1> 	; 07/11/2015
  2445                              <1> 	; 06/11/2015 (serial4.asm, 'serial')
  2446                              <1> 	; 01/11/2015
  2447                              <1> 	; 26/10/2015
  2448                              <1> 	; 23/10/2015
  2449 00003426 53                  <1> 	push	ebx
  2450 00003427 56                  <1> 	push	esi
  2451 00003428 57                  <1> 	push	edi
  2452 00003429 1E                  <1> 	push 	ds
  2453 0000342A 06                  <1> 	push 	es
  2454                              <1> 	; 18/11/2015
  2455 0000342B 0F20DB              <1> 	mov	ebx, cr3
  2456 0000342E 53                  <1> 	push	ebx ; ****
  2457                              <1> 	;
  2458 0000342F 51                  <1> 	push	ecx ; ***
  2459 00003430 52                  <1> 	push	edx ; **
  2460                              <1> 	;
  2461 00003431 BB10000000          <1> 	mov	ebx, KDATA
  2462 00003436 8EDB                <1> 	mov	ds, bx
  2463 00003438 8EC3                <1> 	mov	es, bx
  2464                              <1> 	;
  2465 0000343A 8B0D[D86A0000]      <1> 	mov	ecx, [k_page_dir]
  2466 00003440 0F22D9              <1> 	mov	cr3, ecx
  2467                              <1> 	; 20/11/2015
  2468                              <1> 	; Interrupt identification register
  2469 00003443 66BAFA02            <1> 	mov	dx, 2FAh ; COM2
  2470                              <1> 	;
  2471 00003447 3C08                <1> 	cmp 	al, 8 
  2472 00003449 7702                <1> 	ja 	short com_i0
  2473                              <1> 	;
  2474                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2475                              <1> 	; 20/11/2015
  2476                              <1> 	; 17/11/2015
  2477                              <1> 	; 16/11/2015
  2478                              <1> 	; 15/11/2015
  2479                              <1> 	; 24/10/2015
  2480                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
  2481                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1)
  2482                              <1> 	; < serial port 1 interrupt handler >
  2483                              <1> 	;
  2484 0000344B FEC6                <1> 	inc	dh ; 3FAh ; COM1 Interrupt id. register
  2485                              <1> com_i0:
  2486                              <1> 	;push	eax ; *
  2487                              <1> 	; 07/11/2015
  2488 0000344D A2[466B0000]        <1> 	mov 	byte [ccomport], al
  2489                              <1> 	; 09/11/2015
  2490                              <1> 	;movzx	ebx, ax ; 8 or 9
  2491                              <1> 	; 08/01/2022
  2492 00003452 89C3                <1> 	mov	ebx, eax ; 8 or 9
  2493                              <1> 	; 17/11/2015
  2494                              <1>  	; reset request for response status
  2495 00003454 88A3[3C6B0000]      <1> 	mov	[ebx+req_resp-8], ah ; 0
  2496                              <1> 	;
  2497                              <1> 	; 20/11/2015
  2498 0000345A EC                  <1> 	in	al, dx		; read interrupt id. register
  2499 0000345B EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2500 0000345D 2404                <1> 	and	al, 4		; received data available?	
  2501 0000345F 7470                <1> 	jz	short com_eoi	; (transmit. holding reg. empty)
  2502                              <1> 	;
  2503                              <1> 	; 20/11/2015
  2504 00003461 80EA02              <1> 	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
  2505 00003464 EC                  <1> 	in	al, dx     	; read character
  2506                              <1> 	;JMP	$+2	   	; I/O DELAY
  2507                              <1> 	; 08/11/2015
  2508                              <1> 	; 07/11/2015
  2509 00003465 89DE                <1> 	mov	esi, ebx 
  2510 00003467 89DF                <1> 	mov	edi, ebx
  2511 00003469 81C6[406B0000]      <1> 	add 	esi, rchar - 8 ; points to last received char
  2512 0000346F 81C7[426B0000]      <1> 	add	edi, schar - 8 ; points to last sent char
  2513 00003475 8806                <1> 	mov	[esi], al ; received char (current char)
  2514                              <1> 	; query
  2515 00003477 20C0                <1> 	and	al, al
  2516 00003479 7527                <1> 	jnz	short com_i2
  2517                              <1>    	; response
  2518                              <1> 	; 17/11/2015
  2519                              <1> 	; set request for response status
  2520 0000347B FE83[3C6B0000]      <1>         inc     byte [ebx+req_resp-8] ; 1 
  2521                              <1> 	;
  2522 00003481 6683C205            <1> 	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
  2523 00003485 EC                  <1> 	in	al, dx	   	; read line status register 
  2524 00003486 EB00                <1> 	JMP	$+2	   	; I/O DELAY
  2525 00003488 2420                <1> 	and	al, 20h	   	; transmitter holding reg. empty?
  2526 0000348A 7445                <1> 	jz	short com_eoi 	; no
  2527 0000348C B0FF                <1> 	mov 	al, 0FFh   	; response			
  2528 0000348E 6683EA05            <1> 	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
  2529 00003492 EE                  <1> 	out	dx, al	   	; send on serial port
  2530                              <1> 	; 17/11/2015
  2531 00003493 803F00              <1> 	cmp 	byte [edi], 0   ; query ? (schar)
  2532 00003496 7502                <1> 	jne 	short com_i1    ; no
  2533 00003498 8807                <1> 	mov	[edi], al 	; 0FFh (responded)
  2534                              <1> com_i1:
  2535                              <1> 	; 17/11/2015
  2536                              <1> 	; reset request for response status (again)
  2537 0000349A FE8B[3C6B0000]      <1>         dec     byte [ebx+req_resp-8] ; 0 
  2538 000034A0 EB2F                <1> 	jmp	short com_eoi
  2539                              <1> com_i2:	
  2540                              <1> 	; 08/11/2015
  2541 000034A2 3CFF                <1> 	cmp 	al, 0FFh	; (response ?)
  2542 000034A4 7417                <1> 	je	short com_i3	; (check for response signal)
  2543                              <1> 	; 07/11/2015
  2544 000034A6 3C04                <1> 	cmp	al, 04h	; EOT
  2545 000034A8 751C                <1> 	jne	short com_i4	
  2546                              <1> 	; EOT = 04h (End of Transmit) - 'CTRL + D'
  2547                              <1> 	;(an EOT char is supposed as a ctrl+brk from the terminal)
  2548                              <1> 	; 08/11/2015
  2549                              <1> 		; ptty -> tty 0 to 7 (pseudo screens)
  2550 000034AA 861D[066B0000]      <1> 	xchg	bl, [ptty]  ; tty number (8 or 9)
  2551 000034B0 E80BFFFFFF          <1> 	call 	ctrlbrk
  2552 000034B5 861D[066B0000]      <1> 	xchg	[ptty], bl ; (restore ptty value and BL value)
  2553                              <1> 	;mov	al, 04h ; EOT
  2554                              <1> 	; 08/11/2015
  2555 000034BB EB09                <1> 	jmp	short com_i4	
  2556                              <1> com_i3:
  2557                              <1> 	; 08/11/2015
  2558                              <1> 	; If 0FFh has been received just after a query
  2559                              <1> 	; (schar, ZERO), it is a response signal.
  2560                              <1> 	; 17/11/2015
  2561 000034BD 803F00              <1>         cmp     byte [edi], 0 ; query ? (schar)
  2562 000034C0 7704                <1> 	ja	short com_i4 ; no
  2563                              <1> 	; reset query status (schar)
  2564 000034C2 8807                <1> 	mov	[edi], al ; 0FFh
  2565 000034C4 FEC0                <1> 	inc	al ; 0
  2566                              <1> com_i4:
  2567                              <1> 	; 27/07/2014
  2568                              <1> 	; 09/07/2014
  2569 000034C6 D0E3                <1> 	shl	bl, 1	
  2570 000034C8 81C3[086B0000]      <1> 	add	ebx, ttychr
  2571                              <1> 	; 23/07/2014 (always overwrite)
  2572                              <1> 	;;cmp	word [ebx], 0
  2573                              <1> 	;;ja	short com_eoi
  2574                              <1> 	;
  2575 000034CE 668903              <1> 	mov	[ebx], ax   ; Save ascii code
  2576                              <1> 			    ; scan code = 0
  2577                              <1> com_eoi:
  2578                              <1> 	;mov	al, 20h
  2579                              <1> 	;out	20h, al	   ; end of interrupt
  2580                              <1> 	;
  2581                              <1> 	; 07/11/2015
  2582                              <1>       	;pop	eax ; *
  2583 000034D1 A0[466B0000]        <1> 	mov	al, byte [ccomport] ; current COM port
  2584                              <1> 	; al = tty number (8 or 9)
  2585 000034D6 E8B01A0000          <1>         call	wakeup
  2586                              <1> com_iret:
  2587                              <1> 	; 23/10/2015
  2588 000034DB 5A                  <1> 	pop	edx ; **
  2589 000034DC 59                  <1> 	pop	ecx ; ***
  2590                              <1> 	; 18/11/2015
  2591                              <1> 	;pop	eax ; ****
  2592                              <1> 	;mov	cr3, eax
  2593                              <1> 	;jmp	iiret
  2594 000034DD E9C2D4FFFF          <1> 	jmp	iiretp
  2595                              <1> 
  2596                              <1> ;iiretp: ; 01/09/2015
  2597                              <1> ;	; 28/08/2015
  2598                              <1> ;	pop	eax ; (*) page directory
  2599                              <1> ;	mov	cr3, eax
  2600                              <1> ;iiret:
  2601                              <1> ;	; 22/08/2014
  2602                              <1> ;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
  2603                              <1> ;	out	20h, al	; 8259 PORT
  2604                              <1> ;	;
  2605                              <1> ;	pop	es
  2606                              <1> ;	pop	ds
  2607                              <1> ;	pop	edi
  2608                              <1> ;	pop	esi
  2609                              <1> ;	pop	ebx ; 29/08/2014
  2610                              <1> ;	pop 	eax
  2611                              <1> ;	iretd
  2612                              <1> 
  2613                              <1> sp_init:
  2614                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2615                              <1> 	; 07/11/2015
  2616                              <1> 	; 29/10/2015
  2617                              <1> 	; 26/10/2015
  2618                              <1> 	; 23/10/2015
  2619                              <1> 	; 29/06/2015
  2620                              <1> 	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
  2621                              <1> 	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
  2622                              <1> 	; Initialization of Serial Port Communication Parameters
  2623                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2624                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2625                              <1> 	;
  2626                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2627                              <1> 	;
  2628                              <1> 	; INPUT:  (29/06/2015)
  2629                              <1> 	;	AL = 0 for COM1
  2630                              <1> 	;	     1 for COM2
  2631                              <1> 	;	AH = Communication parameters	
  2632                              <1> 	;
  2633                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2634                              <1> 	;	Bit	4	3	2	1	0
  2635                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2636                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2637                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2638                              <1> 	;		11 = even
  2639                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2640                              <1> 	;		Retro UNIX 386 v1 feature only !
  2641                              <1> 	;	Bit	7    6    5  | Baud rate
  2642                              <1> 	;		------------------------
  2643                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2644                              <1> 	;		0    0    1  | 9600 (12)
  2645                              <1> 	;		0    1    0  | 19200 (6) 
  2646                              <1> 	;		0    1	  1  | 38400 (3) 
  2647                              <1> 	;		1    0	  0  | 14400 (8)
  2648                              <1> 	;		1    0	  1  | 28800 (4)
  2649                              <1> 	;		1    1    0  | 57600 (2)
  2650                              <1> 	;		1    1    1  | 115200 (1) 	
  2651                              <1> 	
  2652                              <1> 	; References:	
  2653                              <1> 	; (1) IBM PC-XT Model 286 BIOS Source Code
  2654                              <1> 	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
  2655                              <1> 	; (2) Award BIOS 1999 - ATORGS.ASM
  2656                              <1> 	; (3) http://wiki.osdev.org/Serial_Ports
  2657                              <1> 	;
  2658                              <1> 	; Set communication parameters for COM1 (= 03h)	
  2659                              <1> 	;
  2660 000034E2 BB[426B0000]        <1> 	mov	ebx, com1p		; COM1 parameters  
  2661 000034E7 66BAF803            <1> 	mov	dx, 3F8h		; COM1
  2662                              <1> 	; 29/10/2015
  2663 000034EB 66B90103            <1> 	mov	cx, 301h  ; divisor = 1 (115200 baud)
  2664 000034EF E84F000000          <1> 	call	sp_i3	; call A4	
  2665 000034F4 A880                <1> 	test	al, 80h
  2666 000034F6 740E                <1> 	jz	short sp_i0 ; OK..
  2667                              <1> 		; Error !
  2668                              <1> 	;mov	dx, 3F8h
  2669 000034F8 80EA05              <1> 	sub	dl, 5 ; 3FDh -> 3F8h
  2670                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2671                              <1> 	; 08/01/2022
  2672 000034FB B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2673 000034FD E841000000          <1> 	call	sp_i3	; call A4	
  2674 00003502 A880                <1> 	test	al, 80h
  2675 00003504 7508                <1> 	jnz	short sp_i1
  2676                              <1> sp_i0:
  2677                              <1>         ; (Note: Serial port interrupts will be disabled here...)	
  2678                              <1>         ; (INT 14h initialization code disables interrupts.)
  2679                              <1> 	;
  2680 00003506 C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2681 00003509 E8BF000000          <1> 	call	sp_i5 ; 29/06/2015
  2682                              <1> sp_i1:
  2683 0000350E 43                  <1> 	inc	ebx
  2684 0000350F 66BAF802            <1> 	mov	dx, 2F8h		; COM2
  2685                              <1> 	; 29/10/2015
  2686                              <1> 	;mov	cx, 301h  ; divisor = 1 (115200 baud)
  2687                              <1> 	; 08/01/2022
  2688 00003513 B101                <1> 	mov	cl, 01h ; cx = 301h, divisor = 1 (115200 baud)
  2689 00003515 E829000000          <1> 	call	sp_i3	; call A4	
  2690 0000351A A880                <1> 	test	al, 80h
  2691 0000351C 740E                <1> 	jz	short sp_i2 ; OK..
  2692                              <1> 		; Error !
  2693                              <1> 	;mov	dx, 2F8h
  2694 0000351E 80EA05              <1> 	sub	dl, 5 ; 2FDh -> 2F8h
  2695                              <1> 	;mov	cx, 30Eh  ; divisor = 12 (9600 baud)
  2696                              <1> 	; 08/01/2022
  2697 00003521 B10E                <1> 	mov	cl, 0Eh ; cx = 30Eh, divisor = 12 (9600 baud)
  2698 00003523 E81B000000          <1> 	call	sp_i3	; call A4	
  2699 00003528 A880                <1> 	test	al, 80h
  2700 0000352A 7516                <1> 	jnz	short sp_i7
  2701                              <1> sp_i2:
  2702 0000352C C603E3              <1> 	mov	byte [ebx], 0E3h ; 11100011b
  2703                              <1> sp_i6:
  2704                              <1> 	;; COM2 - enabling IRQ 3
  2705                              <1> 	; 08/01/2022
  2706 0000352F B4F7                <1> 	mov	ah, 0F7h ; enable IRQ 3 (COM2)
  2707                              <1> 	; 07/11/2015
  2708                              <1> 	; 26/10/2015
  2709                              <1> 	;pushf
  2710                              <1> 	;cli
  2711                              <1> 	;;
  2712                              <1> 	;;mov	dx, 2FCh   		; modem control register
  2713                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2714                              <1> 	;in	al, dx 	   		; read register
  2715                              <1> 	;JMP	$+2	   		; I/O DELAY
  2716                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2717                              <1> 	;out	dx, al     		; write back to register
  2718                              <1> 	;JMP	$+2	   		; I/O DELAY
  2719                              <1> 	;;mov	dx, 2F9h   		; interrupt enable register
  2720                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2721                              <1> 	;in	al, dx     		; read register
  2722                              <1> 	;JMP	$+2	   		; I/O DELAY
  2723                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2724                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2725                              <1> 	;out	dx, al 	   		; write back to register
  2726                              <1> 	;JMP	$+2        		; I/O DELAY
  2727                              <1> 	;in	al, 21h    		; read interrupt mask register
  2728                              <1> 	;JMP	$+2	   		; I/O DELAY
  2729                              <1> 	;and	al, 0F7h   		; enable IRQ 3 (COM2)
  2730                              <1> 	;out	21h, al    		; write back to register
  2731                              <1> 	;
  2732                              <1> 	; 08/01/2022
  2733 00003531 9C                  <1> 	pushf
  2734 00003532 E8AA000000          <1> 	call	sp_i8
  2735                              <1> 	; 23/10/2015
  2736 00003537 B8[16340000]        <1> 	mov 	eax, com2_int
  2737 0000353C A3[D5390000]        <1> 	mov	[com2_irq3], eax
  2738                              <1> 	; 26/10/2015
  2739 00003541 9D                  <1> 	popf	
  2740                              <1> sp_i7:
  2741 00003542 C3                  <1> 	retn
  2742                              <1> 
  2743                              <1> sp_i3:
  2744                              <1> ;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
  2745                              <1> 	; 28/10/2015
  2746 00003543 FEC2                <1> 	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
  2747 00003545 B000                <1> 	mov	al, 0
  2748 00003547 EE                  <1> 	out	dx, al			; disable serial port interrupt
  2749 00003548 EB00                <1> 	JMP	$+2			; I/O DELAY
  2750 0000354A 80C202              <1> 	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
  2751 0000354D B080                <1> 	mov	al, 80h			
  2752 0000354F EE                  <1> 	out	dx, al			; SET DLAB=1 ; divisor latch access bit
  2753                              <1> 	;-----	SET BAUD RATE DIVISOR
  2754                              <1> 	; 26/10/2015
  2755 00003550 80EA03              <1> 	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
  2756                              <1> 					; of the divisor value
  2757 00003553 88C8                <1> 	mov	al, cl	; 1
  2758 00003555 EE                  <1> 	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
  2759                              <1> 					; 2 = 57600 baud
  2760                              <1> 					; 3 = 38400 baud
  2761                              <1> 					; 6 = 19200 baud
  2762                              <1> 					; 12 = 9600 baud (Retro UNIX 8086 v1)
  2763 00003556 EB00                <1> 	JMP	$+2			; I/O DELAY
  2764 00003558 28C0                <1> 	sub	al, al
  2765 0000355A FEC2                <1> 	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
  2766                              <1> 					; of the divisor value
  2767 0000355C EE                  <1> 	out	dx, al ; 0
  2768 0000355D EB00                <1> 	JMP	$+2			; I/O DELAY
  2769                              <1> 	;	
  2770 0000355F 88E8                <1> 	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
  2771                              <1> 	;and	al, 1Fh ; Bits 0,1,2,3,4	
  2772 00003561 80C202              <1> 	add	dl, 2	; 3FBh (2FBh)	; Line control register
  2773 00003564 EE                  <1> 	out	dx, al			
  2774 00003565 EB00                <1> 	JMP	$+2			; I/O DELAY
  2775                              <1> 	; 29/10/2015
  2776 00003567 FECA                <1> 	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
  2777 00003569 30C0                <1> 	xor	al, al			; 0
  2778 0000356B EE                  <1> 	out	dx, al			; Disable FIFOs (reset to 8250 mode)
  2779 0000356C EB00                <1> 	JMP	$+2	
  2780                              <1> sp_i4:
  2781                              <1> ;A18:	;-----	COMM PORT STATUS ROUTINE
  2782                              <1> 	; 29/06/2015 (line status after modem status)
  2783 0000356E 80C204              <1> 	add	dl, 4	; 3FEh (2FEh)	; Modem status register
  2784                              <1> sp_i4s:
  2785 00003571 EC                  <1> 	in	al, dx			; GET MODEM CONTROL STATUS
  2786 00003572 EB00                <1> 	JMP	$+2			; I/O DELAY
  2787 00003574 88C4                <1> 	mov	ah, al			; PUT IN (AH) FOR RETURN
  2788 00003576 FECA                <1> 	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
  2789                              <1> 					; dx = 3FDh for COM1, 2FDh for COM2
  2790 00003578 EC                  <1> 	in	al, dx			; GET LINE CONTROL STATUS
  2791                              <1> 	; AL = Line status, AH = Modem status
  2792 00003579 C3                  <1> 	retn
  2793                              <1> 
  2794                              <1> sp_status:
  2795                              <1> 	; 29/06/2015
  2796                              <1> 	; 27/06/2015 (Retro UNIX 386 v1)
  2797                              <1> 	; Get serial port status
  2798 0000357A 66BAFE03            <1> 	mov	dx, 3FEh		; Modem status register (COM1)
  2799 0000357E 28C6                <1> 	sub	dh, al			; dh = 2 for COM2 (al = 1)
  2800                              <1> 					; dx = 2FEh for COM2
  2801 00003580 EBEF                <1> 	jmp	short sp_i4s
  2802                              <1> 
  2803                              <1> sp_setp: ; Set serial port communication parameters
  2804                              <1> 	; 08/01/2022
  2805                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2806                              <1> 	; 07/11/2015
  2807                              <1> 	; 29/10/2015
  2808                              <1> 	; 29/06/2015
  2809                              <1> 	; Retro UNIX 386 v1 feature only !	
  2810                              <1> 	;
  2811                              <1> 	; INPUT:
  2812                              <1> 	;	AL = 0 for COM1
  2813                              <1> 	;	     1 for COM2
  2814                              <1> 	;	AH = Communication parameters (*)
  2815                              <1> 	; OUTPUT:
  2816                              <1> 	;	CL = Line status
  2817                              <1> 	;	CH = Modem status
  2818                              <1> 	;   If cf = 1 -> Error code in [u.error]
  2819                              <1> 	;		 'invalid parameter !' 
  2820                              <1> 	;		 	 or
  2821                              <1> 	;		 'device not ready !' error
  2822                              <1> 	;	
  2823                              <1> 	;  (*) Communication parameters (except BAUD RATE):
  2824                              <1> 	;	Bit	4	3	2	1	0
  2825                              <1> 	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
  2826                              <1> 	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
  2827                              <1> 	;		01 = odd     1 = 2 bits	10 = 7 bits
  2828                              <1> 	;		11 = even
  2829                              <1> 	;  Baud rate setting bits: (29/06/2015)
  2830                              <1> 	;		Retro UNIX 386 v1 feature only !
  2831                              <1> 	;	Bit	7    6    5  | Baud rate
  2832                              <1> 	;		------------------------
  2833                              <1> 	;	value	0    0    0  | Default (Divisor = 1)
  2834                              <1> 	;		0    0    1  | 9600 (12)
  2835                              <1> 	;		0    1    0  | 19200 (6) 
  2836                              <1> 	;		0    1	  1  | 38400 (3) 
  2837                              <1> 	;		1    0	  0  | 14400 (8)
  2838                              <1> 	;		1    0	  1  | 28800 (4)
  2839                              <1> 	;		1    1    0  | 57600 (2)
  2840                              <1> 	;		1    1    1  | 115200 (1) 
  2841                              <1> 	;
  2842                              <1> 	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
  2843                              <1> 	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
  2844                              <1> 	;
  2845                              <1> 	; ((Modified registers: EAX, ECX, EDX, EBX))
  2846                              <1> 	;
  2847 00003582 66BAF803            <1> 	mov	dx, 3F8h
  2848 00003586 BB[426B0000]        <1> 	mov	ebx, com1p ; COM1 control byte offset
  2849 0000358B 3C01                <1> 	cmp	al, 1
  2850 0000358D 7770                <1> 	ja 	short sp_invp_err
  2851 0000358F 7203                <1> 	jb	short sp_setp1 ;  COM1 (AL = 0)
  2852 00003591 FECE                <1> 	dec	dh ; 2F8h
  2853 00003593 43                  <1> 	inc	ebx ; COM2 control byte offset
  2854                              <1> sp_setp1:
  2855                              <1> 	; 29/10/2015
  2856 00003594 8823                <1> 	mov	[ebx], ah
  2857 00003596 0FB6CC              <1> 	movzx 	ecx, ah
  2858 00003599 C0E905              <1> 	shr	cl, 5 ; -> baud rate index
  2859 0000359C 80E41F              <1> 	and	ah, 1Fh ; communication parameters except baud rate
  2860 0000359F 8A81[0E360000]      <1> 	mov	al, [ecx+b_div_tbl]
  2861 000035A5 6689C1              <1> 	mov	cx, ax
  2862 000035A8 E896FFFFFF          <1> 	call	sp_i3
  2863 000035AD 6689C1              <1> 	mov	cx, ax ; CL = Line status, CH = Modem status
  2864 000035B0 A880                <1> 	test	al, 80h
  2865 000035B2 740F                <1> 	jz	short sp_setp2
  2866 000035B4 C603E3              <1>         mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
  2867                              <1> stp_dnr_err:
  2868 000035B7 C705[ED6E0000]0F00- <1> 	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
  2868 000035BF 0000                <1>
  2869                              <1> 	; CL = Line status, CH = Modem status
  2870 000035C1 F9                  <1> 	stc
  2871 000035C2 C3                  <1> 	retn
  2872                              <1> sp_setp2:
  2873 000035C3 80FE02              <1> 	cmp	dh, 2 ; COM2 (2F?h)
  2874                              <1>         ;jna	sp_i6
  2875                              <1> 		      ; COM1 (3F?h)
  2876                              <1> 	; 24/12/2021
  2877 000035C6 7705                <1> 	ja	short sp_i5
  2878 000035C8 E962FFFFFF          <1> 	jmp	sp_i6
  2879                              <1> sp_i5: 
  2880                              <1> 	; 08/01/2022
  2881 000035CD B4EF                <1> 	mov	ah, 0EFh ; enable IRQ 4 (COM1)
  2882                              <1> 	; 07/11/2015
  2883                              <1> 	; 26/10/2015
  2884                              <1> 	; 29/06/2015
  2885                              <1> 	;
  2886                              <1> 	;; COM1 - enabling IRQ 4
  2887                              <1> 	;pushf
  2888                              <1> 	;cli
  2889                              <1> 	;;mov	dx, 3FCh   		; modem control register
  2890                              <1> 	;mov	dl, 0FCh ; 08/01/2022
  2891                              <1> 	;in	al, dx 	   		; read register
  2892                              <1> 	;JMP	$+2			; I/O DELAY
  2893                              <1> 	;or	al, 8      		; enable bit 3 (OUT2)
  2894                              <1> 	;out	dx, al     		; write back to register
  2895                              <1> 	;JMP	$+2			; I/O DELAY
  2896                              <1> 	;;mov	dx, 3F9h   		; interrupt enable register
  2897                              <1> 	;mov	dl, 0F9h ; 08/01/2022
  2898                              <1> 	;in	al, dx     		; read register
  2899                              <1> 	;JMP	$+2			; I/O DELAY
  2900                              <1> 	;;or	al, 1      		; receiver data interrupt enable and
  2901                              <1> 	;or	al, 3	   		; transmitter empty interrupt enable
  2902                              <1> 	;out	dx, al 	   		; write back to register
  2903                              <1> 	;JMP	$+2        		; I/O DELAY
  2904                              <1> 	;in	al, 21h    		; read interrupt mask register
  2905                              <1> 	;JMP	$+2			; I/O DELAY
  2906                              <1> 	;and	al, 0EFh   		; enable IRQ 4 (COM1)
  2907                              <1> 	;out	21h, al    		; write back to register
  2908                              <1> 	;
  2909                              <1> 	; 08/01/2022
  2910 000035CF 9C                  <1> 	pushf
  2911 000035D0 E80C000000          <1> 	call	sp_i8
  2912                              <1> 	; 23/10/2015
  2913 000035D5 B8[1F340000]        <1> 	mov 	eax, com1_int
  2914 000035DA A3[D1390000]        <1> 	mov	[com1_irq4], eax
  2915                              <1> 	; 26/10/2015
  2916 000035DF 9D                  <1> 	popf
  2917 000035E0 C3                  <1> 	retn
  2918                              <1> 
  2919                              <1> sp_i8:
  2920                              <1> 	; 08/01/2022
  2921                              <1> 	;pushf
  2922 000035E1 FA                  <1> 	cli
  2923                              <1> 	;
  2924                              <1> 	;mov	dx, 2FCh  ; 3FCh	; modem control register
  2925 000035E2 B2FC                <1> 	mov	dl, 0FCh
  2926 000035E4 EC                  <1> 	in	al, dx 	   		; read register
  2927 000035E5 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2928 000035E7 0C08                <1> 	or	al, 8      		; enable bit 3 (OUT2)
  2929 000035E9 EE                  <1> 	out	dx, al     		; write back to register
  2930 000035EA EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2931                              <1> 	;mov	dx, 2F9h  ; 3F9h 	; interrupt enable register
  2932 000035EC B2F9                <1> 	mov	dl, 0F9h
  2933 000035EE EC                  <1> 	in	al, dx     		; read register
  2934 000035EF EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2935                              <1> 	;or	al, 1      		; receiver data interrupt enable and
  2936 000035F1 0C03                <1> 	or	al, 3	   		; transmitter empty interrupt enable
  2937 000035F3 EE                  <1> 	out	dx, al 	   		; write back to register
  2938 000035F4 EB00                <1> 	JMP	$+2        		; I/O DELAY
  2939 000035F6 E421                <1> 	in	al, 21h    		; read interrupt mask register
  2940 000035F8 EB00                <1> 	JMP	$+2	   		; I/O DELAY
  2941                              <1> 	;and	al, 0F7h  ; 0EFh	; enable IRQ 3 (COM2)
  2942 000035FA 20E0                <1> 	and	al, ah	; 0F7h or 0EFh 
  2943 000035FC E621                <1> 	out	21h, al    		; write back to register
  2944                              <1> 	;
  2945                              <1> 	;popf	
  2946 000035FE C3                  <1> 	retn
  2947                              <1> 
  2948                              <1> sp_invp_err:
  2949 000035FF C705[ED6E0000]1700- <1> 	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  2949 00003607 0000                <1>
  2950 00003609 31C9                <1> 	xor	ecx, ecx
  2951 0000360B 49                  <1> 	dec	ecx ; 0FFFFh
  2952 0000360C F9                  <1> 	stc
  2953 0000360D C3                  <1> 	retn
  2954                              <1> 
  2955                              <1> ; 29/10/2015
  2956                              <1> b_div_tbl: ; Baud rate divisor table (115200/divisor)
  2957 0000360E 010C0603080401      <1> 	db	1, 12, 6, 3, 8, 4, 1
  2958                              <1> 
  2959                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (01/09/2014) 
  2960                              <1> epoch:
  2961                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2962                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  2963                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1 - UNIX.ASM)
  2964                              <1> 	; 'epoch' procedure prototype: 
  2965                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  2966                              <1> 	; 14/11/2012
  2967                              <1> 	; unixboot.asm (boot file configuration)
  2968                              <1> 	; version of "epoch" procedure in "unixproc.asm"
  2969                              <1> 	; 21/7/2012
  2970                              <1> 	; 15/7/2012
  2971                              <1> 	; 14/7/2012		
  2972                              <1> 	; Erdogan Tan - RETRO UNIX v0.1
  2973                              <1> 	; compute current date and time as UNIX Epoch/Time
  2974                              <1> 	; UNIX Epoch: seconds since 1/1/1970 00:00:00
  2975                              <1> 	;
  2976                              <1>         ;  ((Modified registers: EAX, EDX, ECX, EBX))  
  2977                              <1> 	;
  2978 00003615 E81B010000          <1> 	call 	get_rtc_time		; Return Current Time
  2979 0000361A 86E9                <1>         xchg 	ch,cl
  2980 0000361C 66890D[46680000]    <1>         mov 	[hour], cx
  2981 00003623 86F2                <1>         xchg 	dh,dl
  2982 00003625 668915[4A680000]    <1>         mov 	[second], dx
  2983                              <1> 	;
  2984 0000362C E835010000          <1>         call 	get_rtc_date		; Return Current Date
  2985 00003631 86E9                <1>         xchg 	ch,cl
  2986 00003633 66890D[40680000]    <1>         mov 	[year], cx
  2987 0000363A 86F2                <1>         xchg 	dh,dl
  2988 0000363C 668915[42680000]    <1>         mov 	[month], dx
  2989                              <1> 	;
  2990 00003643 66B93030            <1> 	mov 	cx, 3030h
  2991                              <1> 	;
  2992 00003647 A0[46680000]        <1> 	mov 	al, [hour] ; Hour
  2993                              <1>         	; AL <= BCD number)
  2994 0000364C D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  2995                              <1> 					; AH = AL / 10h
  2996                              <1> 					; AL = AL MOD 10h
  2997 0000364E D50A                <1>         aad 	; AX= AH*10+AL
  2998 00003650 A2[46680000]        <1> 	mov 	[hour], al
  2999 00003655 A0[47680000]        <1> 	mov 	al, [hour+1] ; Minute
  3000                              <1>         	; AL <= BCD number)
  3001 0000365A D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3002                              <1> 					; AH = AL / 10h
  3003                              <1> 					; AL = AL MOD 10h
  3004 0000365C D50A                <1>         aad 	; AX= AH*10+AL
  3005 0000365E A2[48680000]        <1> 	mov 	[minute], al
  3006 00003663 A0[4A680000]        <1> 	mov 	al, [second] ; Second
  3007                              <1>         	; AL <= BCD number)
  3008 00003668 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3009                              <1> 					; AH = AL / 10h
  3010                              <1> 					; AL = AL MOD 10h
  3011 0000366A D50A                <1>         aad 	; AX= AH*10+AL
  3012 0000366C A2[4A680000]        <1> 	mov 	[second], al
  3013 00003671 66A1[40680000]      <1> 	mov 	ax, [year] ; Year (century)
  3014                              <1>  	;push 	ax
  3015                              <1> 	; 08/01/2022
  3016 00003677 50                  <1> 	push	eax
  3017                              <1> 	   	; AL <= BCD number)
  3018 00003678 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3019                              <1> 					; AH = AL / 10h
  3020                              <1> 					; AL = AL MOD 10h
  3021 0000367A D50A                <1>         aad 	; AX= AH*10+AL
  3022 0000367C B464                <1> 	mov 	ah, 100
  3023 0000367E F6E4                <1> 	mul 	ah
  3024 00003680 66A3[40680000]      <1> 	mov 	[year], ax
  3025                              <1> 	;pop	ax
  3026                              <1> 	; 08/01/2022
  3027 00003686 58                  <1> 	pop	eax
  3028 00003687 88E0                <1> 	mov	al, ah
  3029                              <1>         	; AL <= BCD number)
  3030 00003689 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3031                              <1> 					; AH = AL / 10h
  3032                              <1> 					; AL = AL MOD 10h
  3033 0000368B D50A                <1>         aad 	; AX= AH*10+AL
  3034 0000368D 660105[40680000]    <1> 	add 	[year], ax
  3035 00003694 A0[42680000]        <1> 	mov 	al, [month] ; Month
  3036                              <1>            	; AL <= BCD number)
  3037 00003699 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3038                              <1> 					; AH = AL / 10h
  3039                              <1> 					; AL = AL MOD 10h
  3040 0000369B D50A                <1>         aad 	; AX= AH*10+AL
  3041 0000369D A2[42680000]        <1> 	mov 	[month], al	
  3042 000036A2 A0[43680000]        <1>         mov     al, [month+1]      	; Day
  3043                              <1>            	; AL <= BCD number)
  3044 000036A7 D410                <1>         db 	0D4h,10h		; Undocumented inst. AAM
  3045                              <1> 					; AH = AL / 10h
  3046                              <1> 					; AL = AL MOD 10h
  3047 000036A9 D50A                <1>         aad 	; AX= AH*10+AL
  3048 000036AB A2[44680000]        <1>         mov     [day], al
  3049                              <1> 	
  3050                              <1> convert_to_epoch:
  3051                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit modification)
  3052                              <1> 	; 09/04/2013 (Retro UNIX 8086 v1)
  3053                              <1> 	;
  3054                              <1> 	; ((Modified registers: EAX, EDX, EBX)) 
  3055                              <1> 	;
  3056                              <1> 	; Derived from DALLAS Semiconductor
  3057                              <1> 	; Application Note 31 (DS1602/DS1603)
  3058                              <1> 	; 6 May 1998
  3059 000036B0 29C0                <1> 	sub 	eax, eax
  3060 000036B2 66A1[40680000]      <1> 	mov 	ax, [year]
  3061 000036B8 662DB207            <1> 	sub 	ax, 1970
  3062 000036BC BA6D010000          <1> 	mov 	edx, 365
  3063 000036C1 F7E2                <1> 	mul 	edx
  3064 000036C3 31DB                <1> 	xor 	ebx, ebx
  3065 000036C5 8A1D[42680000]      <1> 	mov 	bl, [month]
  3066 000036CB FECB                <1> 	dec 	bl
  3067 000036CD D0E3                <1> 	shl 	bl, 1
  3068                              <1> 	;sub	edx, edx
  3069 000036CF 668B93[4C680000]    <1> 	mov 	dx, [EBX+DMonth]
  3070 000036D6 8A1D[44680000]      <1>         mov     bl, [day]
  3071 000036DC FECB                <1> 	dec 	bl
  3072 000036DE 01D0                <1> 	add 	eax, edx
  3073 000036E0 01D8                <1> 	add 	eax, ebx
  3074                              <1> 			; EAX = days since 1/1/1970
  3075 000036E2 668B15[40680000]    <1> 	mov 	dx, [year]
  3076 000036E9 6681EAB107          <1> 	sub 	dx, 1969
  3077 000036EE 66D1EA              <1> 	shr 	dx, 1
  3078 000036F1 66D1EA              <1> 	shr 	dx, 1		
  3079                              <1> 		; (year-1969)/4
  3080 000036F4 01D0                <1> 	add 	eax, edx
  3081                              <1> 			; + leap days since 1/1/1970
  3082 000036F6 803D[42680000]02    <1> 	cmp 	byte [month], 2	; if past february
  3083 000036FD 7610                <1> 	jna 	short cte1
  3084 000036FF 668B15[40680000]    <1> 	mov 	dx, [year]
  3085 00003706 6683E203            <1> 	and 	dx, 3 ; year mod 4
  3086 0000370A 7503                <1> 	jnz 	short cte1		
  3087                              <1> 			; and if leap year
  3088 0000370C 83C001              <1> 	add 	eax, 1 	; add this year's leap day (february 29)
  3089                              <1> cte1: 			; compute seconds since 1/1/1970
  3090 0000370F BA18000000          <1> 	mov 	edx, 24
  3091 00003714 F7E2                <1> 	mul	edx
  3092 00003716 8A15[46680000]      <1> 	mov 	dl, [hour]
  3093 0000371C 01D0                <1> 	add 	eax, edx
  3094                              <1> 		; EAX = hours since 1/1/1970 00:00:00
  3095                              <1> 	;mov	ebx, 60
  3096 0000371E B33C                <1> 	mov	bl, 60
  3097 00003720 F7E3                <1> 	mul	ebx
  3098 00003722 8A15[48680000]      <1> 	mov 	dl, [minute]
  3099 00003728 01D0                <1> 	add 	eax, edx
  3100                              <1> 		; EAX = minutes since 1/1/1970 00:00:00
  3101                              <1> 	;mov 	ebx, 60
  3102 0000372A F7E3                <1> 	mul	ebx
  3103 0000372C 8A15[4A680000]      <1> 	mov 	dl, [second]
  3104 00003732 01D0                <1> 	add 	eax, edx
  3105                              <1>  		; EAX -> seconds since 1/1/1970 00:00:00
  3106 00003734 C3                  <1> 	retn
  3107                              <1> 
  3108                              <1> get_rtc_time:
  3109                              <1> 	; 15/03/2015
  3110                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3111                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3112                              <1> 	; INT 1Ah
  3113                              <1> 	; (AH) = 02H  READ THE REAL TIME CLOCK AND RETURN WITH,	:
  3114                              <1> 	;       (CH) = HOURS IN BCD (00-23)			:
  3115                              <1> 	;       (CL) = MINUTES IN BCD (00-59)			:
  3116                              <1> 	;       (DH) = SECONDS IN BCD (00-59)			:
  3117                              <1> 	;       (DL) = DAYLIGHT SAVINGS ENABLE (00-01).		:
  3118                              <1> 	;								
  3119                              <1> RTC_20: 				; GET RTC TIME
  3120 00003735 FA                  <1> 	cli
  3121 00003736 E805D4FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3122 0000373B 7227                <1> 	JC	short RTC_29		; EXIT IF ERROR (CY= 1)
  3123                              <1> 
  3124 0000373D B000                <1> 	MOV	AL, CMOS_SECONDS 	; SET ADDRESS OF SECONDS
  3125 0000373F E8E6D3FFFF          <1> 	CALL	CMOS_READ		; GET SECONDS
  3126 00003744 88C6                <1> 	MOV	DH, AL			; SAVE
  3127 00003746 B00B                <1> 	MOV	AL, CMOS_REG_B		; ADDRESS ALARM REGISTER
  3128 00003748 E8DDD3FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT VALUE OF DSE BIT
  3129 0000374D 2401                <1> 	AND	AL, 00000001B		; MASK FOR VALID DSE BIT
  3130 0000374F 88C2                <1> 	MOV	DL, AL			; SET [DL] TO ZERO FOR NO DSE BIT
  3131 00003751 B002                <1> 	MOV	AL, CMOS_MINUTES 	; SET ADDRESS OF MINUTES
  3132 00003753 E8D2D3FFFF          <1> 	CALL	CMOS_READ		; GET MINUTES
  3133 00003758 88C1                <1> 	MOV	CL, AL			; SAVE
  3134 0000375A B004                <1> 	MOV	AL, CMOS_HOURS		; SET ADDRESS OF HOURS
  3135 0000375C E8C9D3FFFF          <1> 	CALL	CMOS_READ		; GET HOURS
  3136 00003761 88C5                <1> 	MOV	CH, AL			; SAVE
  3137 00003763 F8                  <1> 	CLC				; SET CY= 0
  3138                              <1> RTC_29:
  3139 00003764 FB                  <1> 	sti
  3140 00003765 C3                  <1> 	RETn				; RETURN WITH RESULT IN CARRY FLAG
  3141                              <1> 
  3142                              <1> get_rtc_date:
  3143                              <1> 	; 15/03/2015
  3144                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3145                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3146                              <1> 	; INT 1Ah
  3147                              <1> 	; (AH) = 04H  READ THE DATE FROM THE REAL TIME CLOCK AND RETURN WITH,:
  3148                              <1> 	;      (CH) = CENTURY IN BCD (19 OR 20) 		       :
  3149                              <1> 	;      (CL) = YEAR IN BCD (00-99)			       :
  3150                              <1> 	;      (DH) = MONTH IN BCD (01-12)			       :
  3151                              <1> 	;      (DL) = DAY IN BCD (01-31).		
  3152                              <1> 	;
  3153                              <1> RTC_40: 				; GET RTC DATE
  3154 00003766 FA                  <1> 	cli
  3155 00003767 E8D4D3FFFF          <1> 	CALL	UPD_IPR			; CHECK FOR UPDATE IN PROCESS
  3156 0000376C 7225                <1> 	JC	short RTC_49		; EXIT IF ERROR (CY= 1)
  3157                              <1> 
  3158 0000376E B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH
  3159 00003770 E8B5D3FFFF          <1> 	CALL	CMOS_READ		; READ DAY OF MONTH
  3160 00003775 88C2                <1> 	MOV	DL, AL			; SAVE
  3161 00003777 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH
  3162 00003779 E8ACD3FFFF          <1> 	CALL	CMOS_READ		; READ MONTH
  3163 0000377E 88C6                <1> 	MOV	DH, AL			; SAVE
  3164 00003780 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR
  3165 00003782 E8A3D3FFFF          <1> 	CALL	CMOS_READ		; READ YEAR
  3166 00003787 88C1                <1> 	MOV	CL, AL			; SAVE
  3167 00003789 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY LOCATION
  3168 0000378B E89AD3FFFF          <1> 	CALL	CMOS_READ		; GET CENTURY BYTE
  3169 00003790 88C5                <1> 	MOV	CH, AL			; SAVE
  3170 00003792 F8                  <1> 	CLC				; SET CY=0
  3171                              <1> RTC_49:
  3172 00003793 FB                  <1> 	sti
  3173 00003794 C3                  <1> 	RETn				; RETURN WITH RESULTS IN CARRY FLAG
  3174                              <1> 
  3175                              <1> set_date_time:
  3176                              <1> convert_from_epoch:
  3177                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3178                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3179                              <1> 	; 'convert_from_epoch' procedure prototype: 
  3180                              <1> 	; 	            UNIXCOPY.ASM, 10/03/2013
  3181                              <1> 	;
  3182                              <1> 	; ((Modified registers: EAX, EDX, ECX, EBX))	
  3183                              <1> 	;
  3184                              <1> 	; Derived from DALLAS Semiconductor
  3185                              <1> 	; Application Note 31 (DS1602/DS1603)
  3186                              <1> 	; 6 May 1998
  3187                              <1> 	;
  3188                              <1> 	; INPUT:
  3189                              <1> 	; EAX = Unix (Epoch) Time
  3190                              <1> 	;
  3191 00003795 31D2                <1> 	xor 	edx, edx
  3192 00003797 B93C000000          <1> 	mov 	ecx, 60
  3193 0000379C F7F1                <1> 	div	ecx
  3194                              <1> 	;mov 	[imin], eax  ; whole minutes
  3195                              <1> 			     ; since 1/1/1970
  3196 0000379E 668915[4A680000]    <1> 	mov 	[second], dx ; leftover seconds
  3197 000037A5 29D2                <1> 	sub 	edx, edx
  3198 000037A7 F7F1                <1> 	div	ecx
  3199                              <1> 	;mov 	[ihrs], eax  ; whole hours
  3200                              <1> 	;		     ; since 1/1/1970
  3201 000037A9 668915[48680000]    <1> 	mov 	[minute], dx ; leftover minutes
  3202 000037B0 31D2                <1> 	xor	edx, edx
  3203                              <1> 	;mov 	cx, 24
  3204 000037B2 B118                <1> 	mov 	cl, 24
  3205 000037B4 F7F1                <1> 	div	ecx
  3206                              <1> 	;mov 	[iday], ax   ; whole days
  3207                              <1> 			     ; since 1/1/1970
  3208 000037B6 668915[46680000]    <1> 	mov 	[hour], dx   ; leftover hours
  3209 000037BD 05DB020000          <1> 	add 	eax, 365+366 ; whole day since
  3210                              <1> 			     ; 1/1/1968 	
  3211                              <1> 	;mov 	[iday], ax
  3212 000037C2 50                  <1> 	push 	eax
  3213 000037C3 29D2                <1> 	sub	edx, edx
  3214 000037C5 B9B5050000          <1> 	mov 	ecx, (4*365)+1 ; 4 years = 1461 days
  3215 000037CA F7F1                <1> 	div	ecx
  3216 000037CC 59                  <1> 	pop 	ecx
  3217                              <1> 	;mov 	[lday], ax   ; count of quadyrs (4 years)
  3218 000037CD 6652                <1> 	push 	dx
  3219                              <1> 	;mov 	[qday], dx   ; days since quadyr began
  3220 000037CF 6683FA3C            <1> 	cmp 	dx, 31+29    ; if past feb 29 then
  3221 000037D3 F5                  <1> 	cmc		     ; add this quadyr's leap day
  3222 000037D4 83D000              <1> 	adc 	eax, 0	     ; to # of qadyrs (leap days)
  3223                              <1> 	;mov 	[lday], ax   ; since 1968			  
  3224                              <1> 	;mov 	cx, [iday]
  3225 000037D7 91                  <1> 	xchg 	ecx, eax     ; ECX = lday, EAX = iday		  
  3226 000037D8 29C8                <1> 	sub 	eax, ecx     ; iday - lday
  3227 000037DA B96D010000          <1> 	mov 	ecx, 365
  3228 000037DF 31D2                <1> 	xor	edx, edx
  3229                              <1> 	; EAX = iday-lday, EDX = 0
  3230 000037E1 F7F1                <1> 	div	ecx
  3231                              <1> 	;mov 	[iyrs], ax   ; whole years since 1968
  3232                              <1> 	;jday = iday - (iyrs*365) - lday
  3233                              <1> 	;mov [jday], dx      ; days since 1/1 of current year
  3234                              <1> 	;add	eax, 1968
  3235 000037E3 6605B007            <1> 	add 	ax, 1968     ; compute year
  3236 000037E7 66A3[40680000]      <1> 	mov 	[year], ax
  3237 000037ED 6689D1              <1> 	mov 	cx, dx
  3238                              <1> 	;mov 	dx, [qday]
  3239 000037F0 665A                <1> 	pop 	dx
  3240 000037F2 6681FA6D01          <1> 	cmp 	dx, 365	     ; if qday <= 365 and qday >= 60	
  3241 000037F7 7709                <1> 	ja 	short cfe1   ; jday = jday +1
  3242 000037F9 6683FA3C            <1> 	cmp 	dx, 60       ; if past 2/29 and leap year then
  3243 000037FD F5                  <1>         cmc		     ; add a leap day to the # of whole
  3244 000037FE 6683D100            <1> 	adc 	cx, 0        ; days since 1/1 of current year
  3245                              <1> cfe1:			
  3246                              <1> 	;mov 	[jday], cx
  3247 00003802 66BB0C00            <1> 	mov 	bx, 12       ; estimate month
  3248 00003806 66BA6E01            <1> 	mov 	dx, 366      ; mday, max. days since 1/1 is 365
  3249 0000380A 6683E003            <1> 	and 	ax, 11b      ; year mod 4 (and dx, 3) 
  3250                              <1> cfe2:	; Month calculation  ; 0 to 11  (11 to 0)	
  3251 0000380E 6639D1              <1> 	cmp 	cx, dx       ; mday = # of days passed from 1/1
  3252 00003811 731D                <1> 	jnb 	short cfe3
  3253 00003813 664B                <1> 	dec 	bx           ; month = month - 1
  3254 00003815 66D1E3              <1> 	shl 	bx, 1 
  3255 00003818 668B93[4C680000]    <1> 	mov 	dx, [EBX+DMonth] ; # elapsed days at 1st of month
  3256 0000381F 66D1EB              <1> 	shr 	bx, 1        ; bx = month - 1 (0 to 11)
  3257 00003822 6683FB01            <1> 	cmp	bx, 1        ; if month > 2 and year mod 4  = 0	
  3258 00003826 76E6                <1> 	jna 	short cfe2   ; then mday = mday + 1
  3259 00003828 08C0                <1> 	or 	al, al       ; if past 2/29 and leap year then
  3260 0000382A 75E2                <1> 	jnz 	short cfe2   ; add leap day (to mday)
  3261 0000382C 6642                <1> 	inc 	dx           ; mday = mday + 1
  3262 0000382E EBDE                <1> 	jmp 	short cfe2
  3263                              <1> cfe3:
  3264 00003830 6643                <1> 	inc 	bx	     ; -> bx = month, 1 to 12
  3265 00003832 66891D[42680000]    <1> 	mov 	[month], bx
  3266 00003839 6629D1              <1> 	sub 	cx, dx	     ; day = jday - mday + 1	
  3267 0000383C 6641                <1> 	inc 	cx 			  
  3268 0000383E 66890D[44680000]    <1> 	mov 	[day], cx
  3269                              <1> 	
  3270                              <1> 	; eax, ebx, ecx, edx is changed at return
  3271                              <1> 	; output ->
  3272                              <1> 	; [year], [month], [day], [hour], [minute], [second]
  3273                              <1> 	
  3274                              <1> 	; 15/03/2015 (Retro UNIX 386 v1 - 32 bit version)
  3275                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  3276                              <1> set_date:
  3277 00003845 A0[41680000]        <1>         mov     al, [year+1]
  3278 0000384A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3279 0000384C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3280                              <1> 			     ; AL = AH * 10h + AL
  3281 0000384E 88C5                <1> 	mov 	ch, al ; century (BCD)
  3282 00003850 A0[40680000]        <1> 	mov 	al, [year]
  3283 00003855 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3284 00003857 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3285                              <1> 			     ; AL = AH * 10h + AL
  3286 00003859 88C1                <1> 	mov 	cl, al ; year (BCD)
  3287 0000385B A0[42680000]        <1>         mov 	al, [month]
  3288 00003860 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3289 00003862 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3290                              <1> 			     ; AL = AH * 10h + AL
  3291 00003864 88C6                <1> 	mov 	dh, al ; month (BCD)
  3292 00003866 A0[44680000]        <1> 	mov 	al, [day]
  3293 0000386B D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3294 0000386D D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3295                              <1> 			     ; AL = AH * 10h + AL
  3296 0000386F 88C6                <1> 	mov 	dh, al ; day (BCD)
  3297                              <1> 	; Set real-time clock date
  3298 00003871 E879000000          <1> 	call	set_rtc_date
  3299                              <1> set_time:
  3300                              <1>         ; Read real-time clock time 
  3301                              <1> 	; (get day light saving time bit status)
  3302 00003876 FA                  <1>  	cli
  3303 00003877 E8C4D2FFFF          <1> 	CALL	UPD_IPR 	; CHECK FOR UPDATE IN PROCESS
  3304                              <1> 	; cf = 1 -> al = 0
  3305 0000387C 7207                <1>         jc      short stime1
  3306 0000387E B00B                <1> 	MOV	AL, CMOS_REG_B	; ADDRESS ALARM REGISTER
  3307 00003880 E8A5D2FFFF          <1> 	CALL	CMOS_READ	; READ CURRENT VALUE OF DSE BIT
  3308                              <1> stime1:
  3309 00003885 FB                  <1> 	sti
  3310 00003886 2401                <1> 	AND	AL, 00000001B	; MASK FOR VALID DSE BIT
  3311 00003888 88C2                <1> 	MOV	DL, AL		; SET [DL] TO ZERO FOR NO DSE BIT
  3312                              <1> 	; DL = 1 or 0 (day light saving time)
  3313                              <1> 	;	
  3314 0000388A A0[46680000]        <1> 	mov 	al, [hour]
  3315 0000388F D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3316 00003891 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3317                              <1> 			     ; AL = AH * 10h + AL
  3318 00003893 88C5                <1> 	mov 	ch, al ; hour (BCD)
  3319 00003895 A0[48680000]        <1>         mov     al, [minute]
  3320 0000389A D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3321 0000389C D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3322                              <1> 			     ; AL = AH * 10h + AL
  3323 0000389E 88C1                <1> 	mov 	cl, al       ; minute (BCD)
  3324 000038A0 A0[4A680000]        <1>         mov     al, [second]
  3325 000038A5 D40A                <1> 	aam 	; ah = al / 10, al = al mod 10
  3326 000038A7 D510                <1> 	db 	0D5h, 10h    ; Undocumented inst. AAD
  3327                              <1> 			     ; AL = AH * 10h + AL
  3328 000038A9 88C6                <1> 	mov 	dh, al	     ; second (BCD)
  3329                              <1> 	; Set real-time clock time
  3330                              <1>  	; call	set_rtc_time
  3331                              <1> set_rtc_time:
  3332                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3333                              <1> 	; 15/03/2015
  3334                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3335                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3336                              <1> 	; INT 1Ah
  3337                              <1> 	; (AH) = 03H  SET THE REAL TIME CLOCK USING,			:
  3338                              <1> 	;      (CH) = HOURS IN BCD (00-23)			       	:
  3339                              <1> 	;      (CL) = MINUTES IN BCD (00-59)			       	:
  3340                              <1> 	;      (DH) = SECONDS IN BCD (00-59)			       	:
  3341                              <1> 	;      (DL) = 01 IF DAYLIGHT SAVINGS ENABLE OPTION, ELSE 00.    :
  3342                              <1> 	;								:
  3343                              <1> 	;  NOTE: (DL)= 00 IF DAYLIGHT SAVINGS TIME ENABLE IS NOT ENABLED. :
  3344                              <1> 	;        (DL)= 01 ENABLES TWO SPECIAL UPDATES THE LAST SUNDAY IN  :
  3345                              <1> 	;         APRIL   (1:59:59 --> 3:00:00 AM) AND THE LAST SUNDAY IN :
  3346                              <1> 	;         OCTOBER (1:59:59 --> 1:00:00 AM) THE FIRST TIME.	  :
  3347                              <1> 	;
  3348                              <1> RTC_30: 				; SET RTC TIME
  3349 000038AB FA                  <1> 	cli
  3350 000038AC E88FD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3351 000038B1 7305                <1> 	JNC	short RTC_35		; GO AROUND IF CLOCK OPERATING
  3352 000038B3 E886000000          <1> 	CALL	RTC_STA 		; ELSE TRY INITIALIZING CLOCK
  3353                              <1> RTC_35:
  3354 000038B8 88F4                <1> 	MOV	AH, DH			; GET TIME BYTE - SECONDS
  3355 000038BA B000                <1> 	MOV	AL, CMOS_SECONDS 	; ADDRESS SECONDS
  3356 000038BC E89D000000          <1> 	CALL	CMOS_WRITE		; UPDATE SECONDS
  3357 000038C1 88CC                <1> 	MOV	AH, CL			; GET TIME BYTE - MINUTES
  3358 000038C3 B002                <1> 	MOV	AL, CMOS_MINUTES 	; ADDRESS MINUTES
  3359 000038C5 E894000000          <1> 	CALL	CMOS_WRITE		; UPDATE MINUTES
  3360 000038CA 88EC                <1> 	MOV	AH, CH			; GET TIME BYTE - HOURS
  3361 000038CC B004                <1> 	MOV	AL, CMOS_HOURS		; ADDRESS HOURS
  3362 000038CE E88B000000          <1> 	CALL	CMOS_WRITE		; UPDATE ADDRESS
  3363                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3364 000038D3 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3365 000038D7 E84ED2FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT TIME
  3366 000038DC 2462                <1> 	AND	AL, 01100010B		; MASK FOR VALID BIT POSITIONS
  3367 000038DE 0C02                <1> 	OR	AL, 00000010B		; TURN ON 24 HOUR MODE
  3368 000038E0 80E201              <1> 	AND	DL, 00000001B		; USE ONLY THE DSE BIT
  3369 000038E3 08D0                <1> 	OR	AL, DL			; GET DAY LIGHT SAVINGS TIME BIT (OSE)
  3370 000038E5 86E0                <1> 	XCHG	AH, AL			; PLACE IN WORK REGISTER AND GET ADDRESS
  3371 000038E7 E872000000          <1> 	CALL	CMOS_WRITE		; SET NEW ALARM BITS
  3372 000038EC F8                  <1> 	CLC				; SET CY= 0
  3373 000038ED FB                  <1> 	sti
  3374 000038EE C3                  <1> 	RETn				; RETURN WITH CY= 0
  3375                              <1> 
  3376                              <1> set_rtc_date:
  3377                              <1> 	; 15/04/2015 (257, POSTEQU.INC -> H EQU 256, X EQU H+1)
  3378                              <1> 	; 15/03/2015
  3379                              <1> 	; Derived from IBM PC-XT Model 286 BIOS Source Code
  3380                              <1> 	; BIOS2.ASM ---- 10/06/1985 BIOS INTERRUPT ROUTINES
  3381                              <1> 	; INT 1Ah
  3382                              <1> 	; (AH) = 05H  SET THE DATE INTO THE REAL TIME CLOCK USING, :
  3383                              <1> 	;     (CH) = CENTURY IN BCD (19 OR 20)			   :
  3384                              <1> 	;     (CL) = YEAR IN BCD (00-99)			   :
  3385                              <1> 	;     (DH) = MONTH IN BCD (01-12)			   :
  3386                              <1> 	;     (DL) = DAY IN BCD (01-31).
  3387                              <1> 	;
  3388                              <1> RTC_50: 				; SET RTC DATE
  3389 000038EF FA                  <1> 	cli
  3390 000038F0 E84BD2FFFF          <1> 	CALL	UPD_IPR 		; CHECK FOR UPDATE IN PROCESS
  3391 000038F5 7305                <1> 	JNC	short RTC_55		; GO AROUND IF NO ERROR
  3392 000038F7 E842000000          <1> 	CALL	RTC_STA 		; ELSE INITIALIZE CLOCK
  3393                              <1> RTC_55:
  3394 000038FC 66B80600            <1> 	MOV	AX, CMOS_DAY_WEEK	; ADDRESS OF DAY OF WEEK BYTE
  3395 00003900 E859000000          <1> 	CALL	CMOS_WRITE		; LOAD ZEROS TO DAY OF WEEK
  3396 00003905 88D4                <1> 	MOV	AH, DL			; GET DAY OF MONTH BYTE
  3397 00003907 B007                <1> 	MOV	AL, CMOS_DAY_MONTH	; ADDRESS DAY OF MONTH BYTE
  3398 00003909 E850000000          <1> 	CALL	CMOS_WRITE		; WRITE OF DAY OF MONTH REGISTER
  3399 0000390E 88F4                <1> 	MOV	AH, DH			; GET MONTH
  3400 00003910 B008                <1> 	MOV	AL, CMOS_MONTH		; ADDRESS MONTH BYTE
  3401 00003912 E847000000          <1> 	CALL	CMOS_WRITE		; WRITE MONTH REGISTER
  3402 00003917 88CC                <1> 	MOV	AH, CL			; GET YEAR BYTE
  3403 00003919 B009                <1> 	MOV	AL, CMOS_YEAR		; ADDRESS YEAR REGISTER
  3404 0000391B E83E000000          <1> 	CALL	CMOS_WRITE		; WRITE YEAR REGISTER
  3405 00003920 88EC                <1> 	MOV	AH, CH			; GET CENTURY BYTE
  3406 00003922 B032                <1> 	MOV	AL, CMOS_CENTURY 	; ADDRESS CENTURY BYTE
  3407 00003924 E835000000          <1> 	CALL	CMOS_WRITE		; WRITE CENTURY LOCATION
  3408                              <1> 	;MOV	AX, X*CMOS_REG_B 	; ADDRESS ALARM REGISTER
  3409 00003929 66B80B0B            <1> 	MOV	AX, 257*CMOS_REG_B 	; 
  3410 0000392D E8F8D1FFFF          <1> 	CALL	CMOS_READ		; READ CURRENT SETTINGS
  3411 00003932 247F                <1> 	AND	AL, 07FH 		; CLEAR 'SET BIT'
  3412 00003934 86E0                <1> 	XCHG	AH, AL			; MOVE TO WORK REGISTER
  3413 00003936 E823000000          <1> 	CALL	CMOS_WRITE		; AND START CLOCK UPDATING
  3414 0000393B F8                  <1> 	CLC				; SET CY= 0
  3415 0000393C FB                  <1> 	sti
  3416 0000393D C3                  <1> 	RETn				; RETURN CY=0
  3417                              <1> 
  3418                              <1> 	; 15/03/2015
  3419                              <1> RTC_STA:				; INITIALIZE REAL TIME CLOCK
  3420 0000393E B426                <1> 	mov	ah, 26h
  3421 00003940 B00A                <1> 	mov	al, CMOS_REG_A		; ADDRESS REGISTER A AND LOAD DATA MASK
  3422 00003942 E817000000          <1> 	CALL	CMOS_WRITE		; INITIALIZE STATUS REGISTER A
  3423 00003947 B482                <1> 	mov	ah, 82h
  3424 00003949 B00B                <1> 	mov 	al, CMOS_REG_B		; SET "SET BIT" FOR CLOCK INITIALIZATION
  3425 0000394B E80E000000          <1> 	CALL	CMOS_WRITE		; AND 24 HOUR MODE TO REGISTER B
  3426 00003950 B00C                <1> 	MOV	AL, CMOS_REG_C		; ADDRESS REGISTER C
  3427 00003952 E8D3D1FFFF          <1> 	CALL	CMOS_READ		; READ REGISTER C TO INITIALIZE
  3428 00003957 B00D                <1> 	MOV	AL, CMOS_REG_D		; ADDRESS REGISTER D
  3429                              <1> 	;CALL	CMOS_READ		; READ REGISTER D TO INITIALIZE
  3430                              <1> 	;RETn
  3431                              <1> 	; 12/01/2022
  3432 00003959 E9CCD1FFFF          <1> 	jmp	CMOS_READ
  3433                              <1> 
  3434                              <1> 	; 15/03/2015
  3435                              <1> 	; IBM PC/XT Model 286 BIOS source code ----- 10/06/85 (test4.asm)
  3436                              <1> CMOS_WRITE:			; WRITE (AH) TO LOCATION (AL)
  3437 0000395E 9C                  <1> 	pushf			; SAVE INTERRUPT ENABLE STATUS AND FLAGS
  3438                              <1> 	;push	ax		; SAVE WORK REGISTER VALUES
  3439 0000395F D0C0                <1> 	rol	al, 1		; MOVE NMI BIT TO LOW POSITION
  3440 00003961 F9                  <1> 	stc			; FORCE NMI BIT ON IN CARRY FLAG
  3441 00003962 D0D8                <1> 	rcr	al, 1		; HIGH BIT ON TO DISABLE NMI - OLD IN CY
  3442 00003964 FA                  <1> 	cli			; DISABLE INTERRUPTS
  3443 00003965 E670                <1> 	out	CMOS_PORT, al	; ADDRESS LOCATION AND DISABLE NMI
  3444 00003967 88E0                <1> 	mov	al, ah		; GET THE DATA BYTE TO WRITE
  3445 00003969 E671                <1> 	out	CMOS_DATA, al	; PLACE IN REQUESTED CMOS LOCATION
  3446 0000396B B01E                <1> 	mov	al, CMOS_SHUT_DOWN*2 ; GET ADDRESS OF DEFAULT LOCATION
  3447 0000396D D0D8                <1> 	rcr	al, 1		; PUT ORIGINAL NMI MASK BIT INTO ADDRESS
  3448 0000396F E670                <1> 	out	CMOS_PORT, al	; SET DEFAULT TO READ ONLY REGISTER
  3449 00003971 90                  <1> 	nop			; I/O DELAY
  3450 00003972 E471                <1> 	in	al, CMOS_DATA	; OPEN STANDBY LATCH
  3451                              <1> 	;pop	ax		; RESTORE WORK REGISTERS
  3452 00003974 9D                  <1> 	popf	
  3453 00003975 C3                  <1> 	RETn
  3454                              <1> 
  3455                              <1> bf_init:
  3456                              <1> 	; 14/08/2015
  3457                              <1> 	; 02/07/2015
  3458                              <1> 	; 01/07/2015
  3459                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  3460                              <1> 	; Buffer (pointer) initialization !
  3461                              <1> 	; 
  3462                              <1> 	; 17/07/2013 - 24/07/2013
  3463                              <1> 	; Retro UNIX 8086 v1 (U9.ASM)
  3464                              <1> 	; (Retro UNIX 8086 v1 feature only !)
  3465                              <1> 	;
  3466 00003976 BF[5C6E0000]        <1> 	mov	edi, bufp 
  3467 0000397B B8[507B0000]        <1> 	mov	eax, buffer + (nbuf*520) 
  3468 00003980 29D2                <1> 	sub	edx, edx
  3469 00003982 FECA                <1> 	dec	dl
  3470 00003984 31C9                <1> 	xor	ecx, ecx
  3471 00003986 49                  <1> 	dec	ecx
  3472                              <1> bi0:
  3473 00003987 2D08020000          <1> 	sub	eax, 520 ; 8 header + 512 data
  3474 0000398C AB                  <1> 	stosd
  3475 0000398D 89C6                <1> 	mov	esi, eax
  3476 0000398F 8916                <1> 	mov	[esi], edx ; 000000FFh
  3477                              <1> 			   ; Not a valid device sign
  3478 00003991 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3479                              <1> 		      ; Not a valid block number sign 	 	
  3480 00003994 3D[206F0000]        <1> 	cmp	eax, buffer
  3481 00003999 77EC                <1> 	ja	short bi0
  3482 0000399B B8[507B0000]        <1> 	mov	eax, sb0
  3483 000039A0 AB                  <1> 	stosd
  3484 000039A1 B8[587D0000]        <1> 	mov	eax, sb1
  3485 000039A6 AB                  <1> 	stosd
  3486 000039A7 89C6                <1> 	mov	esi, eax ; offset sb1
  3487 000039A9 8916                <1> 	mov	[esi], edx ; 000000FFh
  3488                              <1> 			   ; Not a valid device sign
  3489 000039AB 894E04              <1> 	mov	[esi+4], ecx ; 0FFFFFFFFh
  3490                              <1> 		      ; Not a valid block number sign 	 
  3491                              <1> 	; 14/08/2015
  3492                              <1> 	;call 	rdev_init
  3493                              <1> 	;retn
  3494                              <1> 
  3495                              <1> rdev_init: ; root device, super block buffer initialization
  3496                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3497                              <1> 	; 14/08/2015
  3498                              <1> 	; Retro UNIX 386 v1 feature only !
  3499                              <1> 	;
  3500                              <1> 	; NOTE: Disk partitions (file systems), logical
  3501                              <1> 	; drive initialization, partition's start sector etc.
  3502                              <1> 	; will be coded here, later in 'ldrv_init'	
  3503                              <1> 
  3504 000039AE 0FB605[CA650000]    <1> 	movzx	eax, byte [boot_drv]
  3505                              <1> rdi_0:
  3506 000039B5 3C80                <1> 	cmp	al, 80h
  3507 000039B7 7202                <1> 	jb	short rdi_1
  3508 000039B9 2C7E                <1> 	sub	al, 7Eh ; 80h = 2 (hd0), 81h = 3 (hd1)
  3509                              <1> rdi_1:
  3510 000039BB A2[806E0000]        <1> 	mov	[rdev], al
  3511 000039C0 BB[507B0000]        <1>         mov	ebx, sb0 ; super block buffer
  3512 000039C5 8903                <1> 	mov 	[ebx], eax
  3513 000039C7 B001                <1> 	mov	al, 1 ; eax = 1
  3514 000039C9 894304              <1> 	mov	[ebx+4], eax ; super block address on disk
  3515                              <1> 	;call 	diskio
  3516                              <1> 	;retn
  3517                              <1> 	; 24/12/2021
  3518 000039CC E97E240000          <1> 	jmp	diskio
  3519                              <1> 
  3520                              <1> ; 23/10/2015
  3521                              <1> com1_irq4:
  3522 000039D1 [D9390000]          <1> 	dd	dummy_retn
  3523                              <1> com2_irq3:
  3524 000039D5 [D9390000]          <1> 	dd	dummy_retn
  3525                              <1> 
  3526                              <1> dummy_retn:
  3527 000039D9 C3                  <1> 	retn
  2096                                  %include 'u1.s'        ; 10/05/2015
  2097                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS1.INC
  2098                              <1> ; Last Modification: 27/02/2022
  2099                              <1> ; ----------------------------------------------------------------------------
  2100                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2101                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2102                              <1> ;
  2103                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2104                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2105                              <1> ; <Bell Laboratories (17/3/1972)>
  2106                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2107                              <1> ;
  2108                              <1> ; Retro UNIX 8086 v1 - U1.ASM (12/07/2014) //// UNIX v1 -> u1.s
  2109                              <1> ;
  2110                              <1> ; ****************************************************************************
  2111                              <1> 
  2112                              <1> unkni: ; / used for all system calls
  2113                              <1> sysent: ; < enter to system call >
  2114                              <1> 	; 08/01/2022
  2115                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2116                              <1> 	; 19/10/2015
  2117                              <1> 	; 21/09/2015
  2118                              <1> 	; 01/07/2015
  2119                              <1> 	; 19/05/2015
  2120                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 10/04/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2122                              <1> 	;
  2123                              <1> 	; 'unkni' or 'sysent' is sytem entry from various traps. 
  2124                              <1> 	; The trap type is determined and an indirect jump is made to 
  2125                              <1> 	; the appropriate system call handler. If there is a trap inside
  2126                              <1> 	; the system a jump to panic is made. All user registers are saved 
  2127                              <1> 	; and u.sp points to the end of the users stack. The sys (trap)
  2128                              <1> 	; instructor is decoded to get the the system code part (see
  2129                              <1> 	; trap instruction in the PDP-11 handbook) and from this 
  2130                              <1> 	; the indirect jump address is calculated. If a bad system call is
  2131                              <1> 	; made, i.e., the limits of the jump table are exceeded, 'badsys'
  2132                              <1> 	; is called. If the call is legitimate control passes to the
  2133                              <1> 	; appropriate system routine.
  2134                              <1> 	;
  2135                              <1> 	; Calling sequence:
  2136                              <1> 	;	Through a trap caused by any sys call outside the system.
  2137                              <1> 	; Arguments:
  2138                              <1> 	;	Arguments of particular system call.	
  2139                              <1> 	; ...............................................................
  2140                              <1> 	;	
  2141                              <1> 	; Retro UNIX 8086 v1 modification: 
  2142                              <1> 	;       System call number is in EAX register.
  2143                              <1> 	;
  2144                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2145                              <1> 	;	registers depending of function details.
  2146                              <1>   	;
  2147                              <1> 	; 16/04/2015
  2148 000039DA 368925[906E0000]    <1>         mov     [ss:u.sp], esp ; Kernel stack points to return address
  2149                              <1> 	; save user registers
  2150 000039E1 1E                  <1> 	push	ds
  2151 000039E2 06                  <1> 	push	es
  2152 000039E3 0FA0                <1> 	push	fs
  2153 000039E5 0FA8                <1> 	push	gs
  2154 000039E7 60                  <1> 	pushad  ; eax, ecx, edx, ebx, esp -before pushad-, ebp, esi, edi
  2155                              <1> 	;
  2156                              <1> 	; ESPACE = esp - [ss:u.sp] ; 4*12 = 48 ; 17/09/2015
  2157                              <1> 	; 	(ESPACE is size of space in kernel stack 
  2158                              <1> 	;	for saving/restoring user registers.)
  2159                              <1> 	;
  2160 000039E8 50                  <1> 	push	eax ; 01/07/2015
  2161 000039E9 66B81000            <1> 	mov     ax, KDATA
  2162 000039ED 8ED8                <1>         mov     ds, ax
  2163 000039EF 8EC0                <1>         mov     es, ax
  2164 000039F1 8EE0                <1>         mov     fs, ax
  2165 000039F3 8EE8                <1>         mov     gs, ax
  2166 000039F5 A1[D86A0000]        <1> 	mov	eax, [k_page_dir]
  2167 000039FA 0F22D8              <1> 	mov	cr3, eax
  2168 000039FD 58                  <1> 	pop	eax ; 01/07/2015
  2169                              <1> 	; 19/10/2015
  2170 000039FE FC                  <1> 	cld
  2171                              <1> 	;
  2172 000039FF FE05[8F6E0000]      <1> 	inc	byte [sysflg]
  2173                              <1> 		; incb sysflg / indicate a system routine is in progress
  2174 00003A05 FB                  <1>         sti 	; 18/01/2014
  2175                              <1> 	;jnz	panic ; 24/05/2013
  2176                              <1> 	; 24/12/2021
  2177 00003A06 7405                <1> 	jz	short _1
  2178 00003A08 E979F9FFFF          <1> 	jmp	panic
  2179                              <1> 		; beq 1f
  2180                              <1> 		; jmp panic ; / called if trap inside system
  2181                              <1> ;1:
  2182                              <1> _1:	; 24/12/2021
  2183                              <1> 	; 16/04/2015
  2184 00003A0D A3[986E0000]        <1> 	mov	[u.r0], eax
  2185 00003A12 8925[946E0000]      <1> 	mov	[u.usp], esp ; kernel stack points to user's registers
  2186                              <1> 	;
  2187                              <1> 		; mov $s.syst+2,clockp
  2188                              <1> 		; mov r0,-(sp) / save user registers 
  2189                              <1> 		; mov sp,u.r0 / pointer to bottom of users stack 
  2190                              <1> 			   ; / in u.r0
  2191                              <1> 		; mov r1,-(sp)
  2192                              <1> 		; mov r2,-(sp)
  2193                              <1> 		; mov r3,-(sp)
  2194                              <1> 		; mov r4,-(sp)
  2195                              <1> 		; mov r5,-(sp)
  2196                              <1> 		; mov ac,-(sp) / "accumulator" register for extended
  2197                              <1> 		             ; / arithmetic unit
  2198                              <1> 		; mov mq,-(sp) / "multiplier quotient" register for the
  2199                              <1> 		             ; / extended arithmetic unit
  2200                              <1> 		; mov sc,-(sp) / "step count" register for the extended
  2201                              <1> 		             ; / arithmetic unit
  2202                              <1> 		; mov sp,u.sp / u.sp points to top of users stack
  2203                              <1> 		; mov 18.(sp),r0 / store pc in r0
  2204                              <1> 		; mov -(r0),r0 / sys inst in r0      10400xxx
  2205                              <1> 		; sub $sys,r0 / get xxx code
  2206 00003A18 C1E002              <1> 	shl	eax, 2
  2207                              <1> 		; asl r0 / multiply by 2 to jump indirect in bytes
  2208 00003A1B 3D94000000          <1> 	cmp	eax, end_of_syscalls - syscalls
  2209                              <1> 		; cmp r0,$2f-1f / limit of table (35) exceeded
  2210                              <1> 	;jnb	short badsys
  2211                              <1> 		; bhis badsys / yes, bad system call
  2212                              <1> 	; 08/01/2022
  2213 00003A20 7205                <1> 	jb	short _2
  2214 00003A22 E95D010000          <1> 	jmp	badsys
  2215                              <1> _2:
  2216                              <1> 	; 08/01/2022
  2217                              <1> 	;cmc
  2218                              <1> 	;pushf	
  2219                              <1> 	;push	eax
  2220 00003A27 8B2D[906E0000]      <1>  	mov 	ebp, [u.sp] ; Kernel stack at the beginning of sys call
  2221                              <1> 	;mov	al, 0FEh ; 11111110b
  2222                              <1> 	;;adc	al, 0 ; al = al + cf
  2223                              <1> 	;and	[ebp+8], al ; flags (reset carry flag)
  2224 00003A2D 806508FE            <1> 	and	byte [ebp+8], 0FEh ; 11111110b ; 25/12/2021
  2225                              <1> 		; bic $341,20.(sp) / set users processor priority to 0 
  2226                              <1> 				 ; / and clear carry bit
  2227                              <1> 	;pop	ebp ; eax
  2228 00003A31 89C5                <1> 	mov	ebp, eax ; 25/12/2021
  2229                              <1> 	;popf
  2230                              <1>         ;;jc	badsys
  2231                              <1> 	; 24/12/2021
  2232                              <1> 	;jnc	short _3  ; 08/01/2022
  2233                              <1> 	;jmp	badsys
  2234                              <1> ;_3:
  2235 00003A33 A1[986E0000]        <1> 	mov	eax, [u.r0]
  2236                              <1> 	; system call registers: EAX, EDX, ECX, EBX, ESI, EDI
  2237 00003A38 FFA5[3E3A0000]      <1> 	jmp	dword [ebp+syscalls]
  2238                              <1> 		; jmp *1f(r0) / jump indirect thru table of addresses
  2239                              <1> 		            ; / to proper system routine.
  2240                              <1> syscalls: ; 1:
  2241                              <1> 	; 21/09/2015
  2242                              <1> 	; 01/07/2015
  2243                              <1> 	; 16/04/2015 (32 bit address modification) 
  2244 00003A3E [4E3B0000]          <1> 	dd sysrele	; / 0
  2245 00003A42 [F63B0000]          <1> 	dd sysexit 	; / 1
  2246 00003A46 [213D0000]          <1> 	dd sysfork 	; / 2
  2247 00003A4A [273E0000]          <1> 	dd sysread 	; / 3
  2248 00003A4E [3A3E0000]          <1> 	dd syswrite 	; / 4
  2249 00003A52 [A33E0000]          <1> 	dd sysopen 	; / 5
  2250 00003A56 [CE3F0000]          <1> 	dd sysclose 	; / 6
  2251 00003A5A [9C3C0000]          <1> 	dd syswait 	; / 7
  2252 00003A5E [4B3F0000]          <1> 	dd syscreat 	; / 8
  2253 00003A62 [87430000]          <1> 	dd syslink 	; / 9
  2254 00003A66 [43440000]          <1> 	dd sysunlink 	; / 10
  2255 00003A6A [0D450000]          <1> 	dd sysexec 	; / 11
  2256 00003A6E [3B4B0000]          <1> 	dd syschdir 	; / 12
  2257 00003A72 [1E4C0000]          <1> 	dd systime 	; / 13
  2258 00003A76 [873F0000]          <1> 	dd sysmkdir 	; / 14
  2259 00003A7A [8B4B0000]          <1> 	dd syschmod 	; / 15
  2260 00003A7E [EE4B0000]          <1> 	dd syschown 	; / 16
  2261 00003A82 [514C0000]          <1> 	dd sysbreak 	; / 17
  2262 00003A86 [CA480000]          <1> 	dd sysstat 	; / 18
  2263 00003A8A [214D0000]          <1> 	dd sysseek 	; / 19
  2264 00003A8E [334D0000]          <1> 	dd systell 	; / 20
  2265 00003A92 [F2570000]          <1> 	dd sysmount 	; / 21
  2266 00003A96 [D1580000]          <1> 	dd sysumount 	; / 22
  2267 00003A9A [AF4D0000]          <1> 	dd syssetuid 	; / 23
  2268 00003A9E [E04D0000]          <1> 	dd sysgetuid 	; / 24
  2269 00003AA2 [2D4C0000]          <1> 	dd sysstime 	; / 25
  2270 00003AA6 [A34D0000]          <1> 	dd sysquit 	; / 26
  2271 00003AAA [974D0000]          <1> 	dd sysintr 	; / 27
  2272 00003AAE [A7480000]          <1> 	dd sysfstat 	; / 28
  2273 00003AB2 [EB3F0000]          <1> 	dd sysemt 	; / 29
  2274 00003AB6 [37400000]          <1> 	dd sysmdate 	; / 30
  2275 00003ABA [91400000]          <1> 	dd sysstty 	; / 31
  2276 00003ABE [7A420000]          <1> 	dd sysgtty 	; / 32
  2277 00003AC2 [32400000]          <1> 	dd sysilgins 	; / 33
  2278 00003AC6 [08610000]          <1> 	dd syssleep 	; 34 ; Retro UNIX 8086 v1 feature only !
  2279                              <1> 			     ; 11/06/2014
  2280 00003ACA [1F610000]          <1> 	dd sysmsg	; 35 ; Retro UNIX 386 v1 feature only !
  2281                              <1> 			     ; 01/07/2015
  2282 00003ACE [F7610000]          <1> 	dd sysgeterr	; 36 ; Retro UNIX 386 v1 feature only !
  2283                              <1> 			     ; 21/09/2015 - get last error number
  2284                              <1> end_of_syscalls:
  2285                              <1> 
  2286                              <1> error:
  2287                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2288                              <1> 	; 17/09/2015
  2289                              <1> 	; 03/09/2015
  2290                              <1> 	; 01/09/2015
  2291                              <1> 	; 09/06/2015
  2292                              <1> 	; 13/05/2015
  2293                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2294                              <1> 	; 10/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2295                              <1> 	;
  2296                              <1> 	; 'error' merely sets the error bit off the processor status (c-bit)
  2297                              <1> 	; then falls right into the 'sysret', 'sysrele' return sequence.
  2298                              <1> 	;
  2299                              <1> 	; INPUTS -> none
  2300                              <1> 	; OUTPUTS ->
  2301                              <1> 	;	processor status - carry (c) bit is set (means error)
  2302                              <1> 	;
  2303                              <1> 	; 26/05/2013 (Stack pointer must be reset here! 
  2304                              <1> 	; 	      Because, jumps to error procedure
  2305                              <1> 	;	      disrupts push-pop nesting balance)
  2306                              <1> 	;
  2307 00003AD2 8B2D[906E0000]      <1> 	mov	ebp, [u.sp] ; interrupt (system call) return (iretd) address
  2308 00003AD8 804D0801            <1> 	or	byte [ebp+8], 1  ; set carry bit of flags register
  2309                              <1> 				 ; (system call will return with cf = 1)
  2310                              <1> 		; bis $1,20.(r1) / set c bit in processor status word below
  2311                              <1> 		               ; / users stack
  2312                              <1> 	; 17/09/2015
  2313 00003ADC 83ED30              <1> 	sub	ebp, ESPACE ; 48 ; total size of stack frame ('sysdefs.inc')
  2314                              <1> 				 ; for saving/restoring user registers	
  2315                              <1> 	;cmp	ebp, [u.usp]
  2316                              <1> 	;je	short err0	
  2317 00003ADF 892D[946E0000]      <1> 	mov	[u.usp], ebp
  2318                              <1> ;err0:
  2319                              <1> 	; 01/09/2015
  2320 00003AE5 8B25[946E0000]      <1> 	mov	esp, [u.usp] 	    ; Retro Unix 8086 v1 modification!
  2321                              <1> 				    ; 10/04/2013
  2322                              <1> 				    ; (If an I/O error occurs during disk I/O,
  2323                              <1> 				    ; related procedures will jump to 'error'
  2324                              <1> 				    ; procedure directly without returning to 
  2325                              <1> 				    ; the caller procedure. So, stack pointer
  2326                              <1>                                     ; must be restored here.)
  2327                              <1> 	; 13/05/2015
  2328                              <1> 	; NOTE: (The last) error code is in 'u.error', it can be retrieved by
  2329                              <1> 	;	'get last error' system call later. 	
  2330                              <1> 
  2331                              <1> 	; 03/09/2015 - 09/06/2015 - 07/08/2013
  2332 00003AEB C605[FF6E0000]00    <1> 	mov 	byte [u.kcall], 0 ; namei_r, mkdir_w reset
  2333                              <1> 
  2334                              <1> sysret: ; < return from system call>
  2335                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2336                              <1> 	; 10/09/2015
  2337                              <1> 	; 29/07/2015
  2338                              <1> 	; 25/06/2015
  2339                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2340                              <1> 	; 10/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2341                              <1> 	;
  2342                              <1> 	; 'sysret' first checks to see if process is about to be 
  2343                              <1> 	; terminated (u.bsys). If it is, 'sysexit' is called.
  2344                              <1> 	; If not, following happens:	 
  2345                              <1> 	; 	1) The user's stack pointer is restored.
  2346                              <1> 	;	2) r1=0 and 'iget' is called to see if last mentioned
  2347                              <1> 	;	   i-node has been modified. If it has, it is written out
  2348                              <1> 	;	   via 'ppoke'.
  2349                              <1> 	;	3) If the super block has been modified, it is written out
  2350                              <1> 	;	   via 'ppoke'.				
  2351                              <1> 	;	4) If the dismountable file system's super block has been
  2352                              <1> 	;	   modified, it is written out to the specified device
  2353                              <1> 	;	   via 'ppoke'.
  2354                              <1> 	;	5) A check is made if user's time quantum (uquant) ran out
  2355                              <1> 	;	   during his execution. If so, 'tswap' is called to give
  2356                              <1> 	;	   another user a chance to run.
  2357                              <1> 	;	6) 'sysret' now goes into 'sysrele'. 
  2358                              <1> 	;	    (See 'sysrele' for conclusion.)		
  2359                              <1> 	;
  2360                              <1> 	; Calling sequence:
  2361                              <1> 	;	jump table or 'br sysret'
  2362                              <1> 	; Arguments: 
  2363                              <1> 	;	-	
  2364                              <1> 	; ...............................................................
  2365                              <1> 	;	
  2366                              <1> 	; ((AX=r1 for 'iget' input))
  2367                              <1> 	;	
  2368                              <1> 	;xor	ax, ax ; 04/05/2013
  2369                              <1> 	; 24/12/2021
  2370 00003AF2 31C0                <1> 	xor	eax, eax
  2371                              <1> sysret0: ; 29/07/2015 (eax = 0, jump from sysexec)
  2372 00003AF4 FEC0                <1> 	inc	al ; 04/05/2013
  2373 00003AF6 3805[E66E0000]      <1> 	cmp	[u.bsys], al ; 1
  2374                              <1> 		; tstb u.bsys / is a process about to be terminated because
  2375                              <1> 	;jnb	sysexit ; 04/05/2013
  2376                              <1> 	;	; bne sysexit / of an error? yes, go to sysexit
  2377                              <1> 	; 24/12/2021
  2378 00003AFC 720F                <1> 	jb	short _3
  2379 00003AFE C705[ED6E0000]0100- <1> 	mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2379 00003B06 0000                <1>
  2380 00003B08 E9E9000000          <1> 	jmp	sysexit
  2381                              <1> _3:
  2382                              <1> 	;mov	esp, [u.usp] ; 24/05/2013 (that is not needed here)
  2383                              <1> 		; mov u.sp,sp / no point stack to users stack
  2384 00003B0D FEC8                <1> 	dec 	al ; mov ax, 0
  2385                              <1> 		; clr r1 / zero r1 to check last mentioned i-node
  2386 00003B0F E886160000          <1> 	call	iget
  2387                              <1> 		; jsr r0,iget / if last mentioned i-node has been modified
  2388                              <1> 		            ; / it is written out
  2389                              <1> 	;xor 	ax, ax ; 0
  2390                              <1> 	; 24/12/2021
  2391 00003B14 31C0                <1> 	xor	eax, eax
  2392 00003B16 3805[8D6E0000]      <1> 	cmp	[smod], al ; 0
  2393                              <1> 		; tstb	smod / has the super block been modified
  2394 00003B1C 7614                <1> 	jna	short sysret1
  2395                              <1> 		; beq	1f / no, 1f
  2396 00003B1E A2[8D6E0000]        <1> 	mov	[smod], al ; 0
  2397                              <1> 		; clrb smod / yes, clear smod
  2398 00003B23 BB[507B0000]        <1> 	mov	ebx, sb0 ;; 07/08//2013
  2399 00003B28 66810B0002          <1>    	or	word [ebx], 200h ;;
  2400                              <1> 	;or	word [sb0], 200h ; write bit, bit 9
  2401                              <1> 		; bis $1000,sb0 / set write bit in I/O queue for super block
  2402                              <1> 		      	      ; / output
  2403                              <1> 	; AX = 0
  2404 00003B2D E805220000          <1> 	call 	poke ; 07/08/2013
  2405                              <1> 	; call	ppoke
  2406                              <1> 	; AX = 0
  2407                              <1> 		; jsr r0,ppoke / write out modified super block to disk
  2408                              <1> sysret1: ;1:
  2409 00003B32 3805[8E6E0000]      <1> 	cmp	[mmod], al ; 0
  2410                              <1> 		; tstb	mmod / has the super block for the dismountable file
  2411                              <1> 		           ; / system
  2412 00003B38 7614                <1> 	jna	short sysrel0
  2413                              <1> 		; beq 1f / been modified?  no, 1f
  2414 00003B3A A2[8E6E0000]        <1> 	mov	[mmod], al ; 0	
  2415                              <1> 		; clrb	mmod / yes, clear mmod
  2416                              <1>         ;mov    ax, [mntd]
  2417                              <1>         ;;mov   al, [mdev] ; 26/04/2013
  2418 00003B3F BB[587D0000]        <1> 	mov	ebx, sb1 ;; 07/08//2013
  2419                              <1>         ;;mov	[ebx], al
  2420                              <1> 	;mov    [sb1], al
  2421                              <1> 		; movb	mntd,sb1 / set the I/O queue
  2422 00003B44 66810B0002          <1> 	or	word [ebx], 200h
  2423                              <1> 	;or	word [sb1], 200h ; write bit, bit 9
  2424                              <1> 		; bis $1000,sb1 / set write bit in I/O queue for detached sb
  2425 00003B49 E8E9210000          <1> 	call	poke ; 07/08/2013
  2426                              <1> 	;call	ppoke 
  2427                              <1> 		; jsr r0,ppoke / write it out to its device
  2428                              <1>         ;xor    al, al ; 26/04/2013       
  2429                              <1> ;1:
  2430                              <1> 		; tstb uquant / is the time quantum 0?
  2431                              <1> 		; bne 1f / no, don't swap it out
  2432                              <1> 
  2433                              <1> sysrele: ; < release >
  2434                              <1> 	; 14/10/2015
  2435                              <1> 	; 01/09/2015
  2436                              <1> 	; 24/07/2015
  2437                              <1> 	; 14/05/2015
  2438                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2439                              <1> 	; 10/04/2013 - 07/03/2014 (Retro UNIX 8086 v1)
  2440                              <1> 	;
  2441                              <1> 	; 'sysrele' first calls 'tswap' if the time quantum for a user is
  2442                              <1> 	;  zero (see 'sysret'). It then restores the user's registers and
  2443                              <1> 	; turns off the system flag. It then checked to see if there is
  2444                              <1> 	; an interrupt from the user by calling 'isintr'. If there is, 
  2445                              <1> 	; the output gets flashed (see isintr) and interrupt action is
  2446                              <1> 	; taken by a branch to 'intract'. If there is no interrupt from
  2447                              <1> 	; the user, a rti is made.
  2448                              <1> 	;
  2449                              <1> 	; Calling sequence:
  2450                              <1> 	;	Fall through a 'bne' in 'sysret' & ?
  2451                              <1> 	; Arguments:
  2452                              <1> 	;	-	
  2453                              <1> 	; ...............................................................
  2454                              <1> 	;	
  2455                              <1> 	; 23/02/2014 (swapret)
  2456                              <1> 	; 22/09/2013
  2457                              <1> sysrel0: ;1:
  2458 00003B4E 803D[DA6E0000]00    <1> 	cmp	byte [u.quant], 0 ; 16/05/2013
  2459                              <1> 		; tstb uquant / is the time quantum 0?
  2460 00003B55 7705                <1>         ja      short swapret
  2461                              <1> 		; bne 1f / no, don't swap it out
  2462                              <1> sysrelease: ; 07/12/2013 (jump from 'clock')
  2463 00003B57 E8D4120000          <1> 	call	tswap
  2464                              <1> 		; jsr r0,tswap / yes, swap it out
  2465                              <1> ;
  2466                              <1> ; Retro Unix 8086 v1 feature: return from 'swap' to 'swapret' address.
  2467                              <1> swapret: ;1:
  2468                              <1> 	; 10/09/2015
  2469                              <1> 	; 01/09/2015
  2470                              <1> 	; 14/05/2015
  2471                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit, pm modifications)
  2472                              <1> 	; 26/05/2013 (Retro UNIX 8086 v1)
  2473                              <1> 	; cli
  2474                              <1> 	; 24/07/2015
  2475                              <1> 	;
  2476                              <1> 	;; 'esp' must be already equal to '[u.usp]' here ! 
  2477                              <1> 	;; mov	esp, [u.usp]
  2478                              <1> 
  2479                              <1> 	; 22/09/2013
  2480 00003B5C E8A6140000          <1> 	call	isintr
  2481                              <1> 	; 20/10/2013
  2482 00003B61 7405                <1> 	jz	short sysrel1
  2483 00003B63 E877000000          <1> 	call	intract
  2484                              <1> 		; jsr r0,isintr / is there an interrupt from the user
  2485                              <1> 		;     br intract / yes, output gets flushed, take interrupt
  2486                              <1> 		               ; / action
  2487                              <1> sysrel1:
  2488 00003B68 FA                  <1> 	cli ; 14/10/2015
  2489 00003B69 FE0D[8F6E0000]      <1> 	dec	byte [sysflg]
  2490                              <1> 		; decb sysflg / turn system flag off
  2491 00003B6F A1[F16E0000]        <1> 	mov     eax, [u.pgdir]
  2492 00003B74 0F22D8              <1> 	mov	cr3, eax  ; 1st PDE points to Kernel Page Table 0 (1st 4 MB)
  2493                              <1> 			  ; (others are different than kernel page tables) 
  2494                              <1> 	; 10/09/2015
  2495 00003B77 61                  <1> 	popad ; edi, esi, ebp, temp (icrement esp by 4), ebx, edx, ecx, eax
  2496                              <1> 		; mov (sp)+,sc / restore user registers
  2497                              <1> 		; mov (sp)+,mq
  2498                              <1> 		; mov (sp)+,ac
  2499                              <1> 		; mov (sp)+,r5
  2500                              <1> 		; mov (sp)+,r4
  2501                              <1> 		; mov (sp)+,r3
  2502                              <1> 		; mov (sp)+,r2
  2503                              <1> 	;
  2504 00003B78 A1[986E0000]        <1> 	mov	eax, [u.r0]  ; ((return value in EAX))
  2505 00003B7D 0FA9                <1> 	pop	gs
  2506 00003B7F 0FA1                <1> 	pop	fs
  2507 00003B81 07                  <1> 	pop	es
  2508 00003B82 1F                  <1> 	pop	ds
  2509 00003B83 CF                  <1> 	iretd	
  2510                              <1> 		; rti / no, return from interrupt
  2511                              <1> 
  2512                              <1> badsys:
  2513                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2514                              <1> 	; (Major Modification: 'core' dumping procedure in
  2515                              <1>         ;       original UNIX v1 and Retro UNIX 8086 v1
  2516                              <1> 	;	has been changed to print 'Invalid System Call !'
  2517                              <1> 	;	message on the user's console tty.)
  2518                              <1> 	; (EIP, EAX values will be shown on screen with error message)
  2519                              <1> 	; (EIP = Return address just after the system call -INT 30h-)
  2520                              <1> 	; (EAX = Function number)  
  2521                              <1> 	;
  2522 00003B84 FE05[E66E0000]      <1> 	inc	byte [u.bsys]
  2523                              <1> 	;
  2524 00003B8A 8B1D[906E0000]      <1> 	mov	ebx, [u.sp] ; esp at the beginning of 'sysent'
  2525 00003B90 8B03                <1> 	mov	eax, [ebx] ; EIP (return address, not 'INT 30h' address)
  2526 00003B92 E861DBFFFF          <1> 	call	dwordtohex
  2527 00003B97 8915[34680000]      <1> 	mov	[bsys_msg_eip], edx
  2528 00003B9D A3[38680000]        <1> 	mov	[bsys_msg_eip+4], eax
  2529 00003BA2 A1[986E0000]        <1> 	mov	eax, [u.r0]
  2530 00003BA7 E84CDBFFFF          <1> 	call	dwordtohex
  2531 00003BAC 8915[24680000]      <1> 	mov	[bsys_msg_eax], edx
  2532 00003BB2 A3[28680000]        <1> 	mov	[bsys_msg_eax+4], eax
  2533                              <1> 	; 24/12/2021
  2534                              <1> 	;xor	eax, eax
  2535                              <1> 	;mov	dword [u.base], badsys_msg ; "Invalid System Call !"
  2536                              <1> 	;mov	ebx, [u.fofp]
  2537                              <1> 	;mov	[ebx], eax
  2538                              <1> 	;;mov	eax, 1 ; inode number of console tty (for user)	
  2539                              <1> 	;inc	eax
  2540                              <1> 	;mov	dword [u.count], BSYS_M_SIZE
  2541                              <1> 		; writei
  2542                              <1> 		; INPUTS ->
  2543                              <1> 		;    r1 - inode number
  2544                              <1> 		;    u.count - byte count to be written
  2545                              <1> 		;    u.base - points to user buffer
  2546                              <1> 		;    u.fofp - points to word with current file offset
  2547                              <1> 		; OUTPUTS ->
  2548                              <1> 		;    u.count - cleared
  2549                              <1> 		;    u.nread - accumulates total bytes passed back	
  2550                              <1> 		;
  2551                              <1> 		; ((Modified registers: EDX, EBX, ECX, ESI, EDI, EBP)) 	
  2552                              <1> 	;call	writei
  2553                              <1> 	;;mov	eax, 1
  2554                              <1> 	;jmp	sysexit
  2555                              <1> 
  2556                              <1> 	; 24/12/2021 - Retro UNIX 386 v1.1
  2557 00003BB7 BE[05680000]        <1> 	mov	esi, badsys_msg ; "Invalid System Call !"
  2558 00003BBC 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2559 00003BC3 8A83[F76B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2560 00003BC9 C605[076B0000]0F    <1> 	mov	byte [ccolor], 0Fh ; white (message) color
  2561 00003BD0 A2[EC6E0000]        <1> 	mov 	[u.ttyn], al ; current (active) tty (for user)
  2562 00003BD5 E802260000          <1> 	call	print_cmsg
  2563                              <1> 	;mov	dword [u.error], ERR_INV_FUNC ; 1 ; 'invalid system call !'
  2564 00003BDA E9F3FEFFFF          <1> 	jmp	error
  2565                              <1> 
  2566                              <1> 		; incb u.bsys / turn on the user's bad-system flag
  2567                              <1> 		; mov $3f,u.namep / point u.namep to "core\0\0"
  2568                              <1> 		; jsr r0,namei / get the i-number for the core image file
  2569                              <1> 		; br 1f / error
  2570                              <1> 		; neg r1 / negate the i-number to open the core image file
  2571                              <1> 		       ; / for writing
  2572                              <1> 		; jsr r0,iopen / open the core image file
  2573                              <1> 		; jsr r0,itrunc / free all associated blocks
  2574                              <1> 		; br 2f
  2575                              <1> ;1:
  2576                              <1> 		; mov $17,r1 / put i-node mode (17) in r1
  2577                              <1> 		; jsr r0,maknod / make an i-node
  2578                              <1> 		; mov u.dirbuf,r1 / put i-node number in r1
  2579                              <1> ;2:
  2580                              <1> 		; mov $core,u.base / move address core to u.base
  2581                              <1> 		; mov $ecore-core,u.count / put the byte count in u.count
  2582                              <1> 		; mov $u.off,u.fofp / more user offset to u.fofp
  2583                              <1> 		; clr u.off / clear user offset
  2584                              <1> 		; jsr r0,writei / write out the core image to the user
  2585                              <1> 		; mov $user,u.base / pt. u.base to user
  2586                              <1> 		; mov $64.,u.count / u.count = 64
  2587                              <1> 		; jsr r0,writei / write out all the user parameters
  2588                              <1> 		; neg r1 / make i-number positive
  2589                              <1> 		; jsr r0,iclose / close the core image file
  2590                              <1> 		; br sysexit /
  2591                              <1> ;3:
  2592                              <1> 		; <core\0\0>
  2593                              <1> 
  2594                              <1> intract: ; / interrupt action
  2595                              <1> 	; 14/10/2015
  2596                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2597                              <1> 	; 09/05/2013 - 07/12/2013 (Retro UNIX 8086 v1)
  2598                              <1> 	;
  2599                              <1> 	; Retro UNIX 8086 v1 modification !
  2600                              <1> 	; (Process/task switching and quit routine by using
  2601                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2602                              <1> 	;
  2603                              <1> 	; input -> 'u.quit'  (also value of 'u.intr' > 0)
  2604                              <1> 	; output -> If value of 'u.quit' = FFFFh ('ctrl+brk' sign)
  2605                              <1> 	;		'intract' will jump to 'sysexit'.
  2606                              <1> 	;	    Intract will return to the caller 
  2607                              <1> 	;		if value of 'u.quit' <> FFFFh. 	 
  2608                              <1> 	; 14/10/2015
  2609 00003BDF FB                  <1> 	sti
  2610                              <1> 	; 07/12/2013	
  2611 00003BE0 66FF05[DE6E0000]    <1> 	inc 	word [u.quit]
  2612 00003BE7 7408                <1> 	jz	short intrct0 ; FFFFh -> 0
  2613 00003BE9 66FF0D[DE6E0000]    <1> 	dec	word [u.quit]
  2614                              <1> 	; 16/04/2015
  2615 00003BF0 C3                  <1> 	retn
  2616                              <1> intrct0:	
  2617 00003BF1 58                  <1> 	pop	eax ; call intract -> retn
  2618                              <1> 	;
  2619 00003BF2 31C0                <1> 	xor 	eax, eax
  2620 00003BF4 FEC0                <1> 	inc	al  ; mov ax, 1
  2621                              <1> ;;;
  2622                              <1> 	; UNIX v1 original 'intract' routine... 
  2623                              <1> 	; / interrupt action
  2624                              <1> 		;cmp *(sp),$rti / are you in a clock interrupt?
  2625                              <1> 		; bne 1f / no, 1f
  2626                              <1> 		; cmp (sp)+,(sp)+ / pop clock pointer
  2627                              <1> 	; 1: / now in user area
  2628                              <1> 		; mov r1,-(sp) / save r1
  2629                              <1> 		; mov u.ttyp,r1 
  2630                              <1> 			; / pointer to tty buffer in control-to r1
  2631                              <1> 		; cmpb 6(r1),$177
  2632                              <1> 			; / is the interrupt char equal to "del"
  2633                              <1> 		; beq 1f / yes, 1f
  2634                              <1> 		; clrb 6(r1) 
  2635                              <1> 		        ; / no, clear the byte 
  2636                              <1> 			; / (must be a quit character)
  2637                              <1> 		; mov (sp)+,r1 / restore r1
  2638                              <1> 		; clr u.quit / clear quit flag
  2639                              <1> 		; bis $20,2(sp) 
  2640                              <1> 		    	; / set trace for quit (sets t bit of 
  2641                              <1> 			; / ps-trace trap)
  2642                              <1> 		; rti   ;  / return from interrupt
  2643                              <1> 	; 1: / interrupt char = del
  2644                              <1> 		; clrb 6(r1) / clear the interrupt byte 
  2645                              <1> 			   ; / in the buffer
  2646                              <1> 		; mov (sp)+,r1 / restore r1
  2647                              <1> 		; cmp u.intr,$core / should control be 
  2648                              <1> 				; / transferred to loc core?
  2649                              <1> 		; blo 1f
  2650                              <1> 		; jmp *u.intr / user to do rti yes, 
  2651                              <1> 				; / transfer to loc core
  2652                              <1> 	; 1:
  2653                              <1> 		; sys 1 / exit
  2654                              <1> 
  2655                              <1> sysexit: ; <terminate process>
  2656                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2657                              <1> 	; 01/09/2015
  2658                              <1> 	; 31/08/2015
  2659                              <1> 	; 14/05/2015
  2660                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2661                              <1> 	; 19/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2662                              <1> 	;
  2663                              <1> 	; 'sysexit' terminates a process. First each file that
  2664                              <1> 	; the process has opened is closed by 'flose'. The process
  2665                              <1> 	; status is then set to unused. The 'p.pid' table is then
  2666                              <1> 	; searched to find children of the dying process. If any of
  2667                              <1> 	; children are zombies (died by not waited for), they are
  2668                              <1> 	; set free. The 'p.pid' table is then searched to find the
  2669                              <1> 	; dying process's parent. When the parent is found, it is
  2670                              <1> 	; checked to see if it is free or it is a zombie. If it is
  2671                              <1> 	; one of these, the dying process just dies. If it is waiting
  2672                              <1> 	; for a child process to die, it notified that it doesn't 
  2673                              <1> 	; have to wait anymore by setting it's status from 2 to 1
  2674                              <1> 	; (waiting to active). It is awakened and put on runq by
  2675                              <1> 	; 'putlu'. The dying process enters a zombie state in which
  2676                              <1> 	; it will never be run again but stays around until a 'wait'
  2677                              <1> 	; is completed by it's parent process. If the parent is not
  2678                              <1> 	; found, process just dies. This means 'swap' is called with
  2679                              <1> 	; 'u.uno=0'. What this does is the 'wswap' is not called
  2680                              <1> 	; to write out the process and 'rswap' reads the new process
  2681                              <1> 	; over the one that dies..i.e., the dying process is 
  2682                              <1> 	; overwritten and destroyed.	
  2683                              <1>  	;
  2684                              <1> 	; Calling sequence:
  2685                              <1> 	;	sysexit or conditional branch.
  2686                              <1> 	; Arguments:
  2687                              <1> 	;	-	
  2688                              <1> 	; ...............................................................
  2689                              <1> 	;	
  2690                              <1> 	; Retro UNIX 8086 v1 modification: 
  2691                              <1> 	;       System call number (=1) is in EAX register.
  2692                              <1> 	;
  2693                              <1> 	;       Other parameters are in EDX, EBX, ECX, ESI, EDI, EBP
  2694                              <1> 	;       registers depending of function details.
  2695                              <1> 	;
  2696                              <1> 	; ('swap' procedure is mostly different than original UNIX v1.)
  2697                              <1> 	;
  2698                              <1> ; / terminate process
  2699                              <1> 	; AX = 1
  2700                              <1> 	;dec 	ax ; 0
  2701                              <1> 	; 24/12/2021
  2702 00003BF6 48                  <1> 	dec	eax ; 0
  2703                              <1> 	;dec 	ax ; 0
  2704 00003BF7 66A3[DC6E0000]      <1> 	mov	[u.intr], ax ; 0
  2705                              <1> 		; clr u.intr / clear interrupt control word
  2706                              <1> 		; clr r1 / clear r1
  2707                              <1> 	; AX = 0
  2708                              <1> sysexit_1: ; 1:
  2709                              <1> 	; AX = File descriptor
  2710                              <1> 		; / r1 has file descriptor (index to u.fp list)
  2711                              <1> 		; / Search the whole list
  2712 00003BFD E85A0D0000          <1> 	call	fclose
  2713                              <1> 		; jsr r0,fclose / close all files the process opened
  2714                              <1> 	;; ignore error return
  2715                              <1> 		; br .+2 / ignore error return
  2716                              <1> 	;inc	ax
  2717 00003C02 FEC0                <1> 	inc	al
  2718                              <1> 		; inc r1 / increment file descriptor
  2719                              <1> 	;cmp	ax, 10
  2720 00003C04 3C0A                <1> 	cmp	al, 10
  2721                              <1> 		; cmp r1,$10. / end of u.fp list?
  2722 00003C06 72F5                <1> 	jb	short sysexit_1
  2723                              <1> 		; blt 1b / no, go back
  2724 00003C08 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2725                              <1> 		; movb	u.uno,r1 / yes, move dying process's number to r1
  2726 00003C0F 88A3[176C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2727                              <1> 		; clrb p.stat-1(r1) / free the process
  2728                              <1> 	;shl	bx, 1
  2729 00003C15 D0E3                <1> 	shl	bl, 1
  2730                              <1> 		; asl r1 / use r1 for index into the below tables
  2731 00003C17 668B8B[B66B0000]    <1> 	mov	cx, [ebx+p.pid-2]
  2732                              <1> 		; mov p.pid-2(r1),r3 / move dying process's name to r3
  2733 00003C1E 668B93[D66B0000]    <1> 	mov	dx, [ebx+p.ppid-2]
  2734                              <1> 		; mov p.ppid-2(r1),r4 / move its parents name to r4
  2735                              <1> 	; xor 	bx, bx ; 0
  2736 00003C25 30DB                <1> 	xor	bl, bl ; 0
  2737                              <1> 		; clr r2
  2738 00003C27 31F6                <1> 	xor	esi, esi ; 0
  2739                              <1> 		; clr r5 / initialize reg
  2740                              <1> sysexit_2: ; 1:
  2741                              <1> 	        ; / find children of this dying process, 
  2742                              <1> 		; / if they are zombies, free them
  2743                              <1> 	;add	bx, 2
  2744 00003C29 80C302              <1> 	add	bl, 2
  2745                              <1> 		; add $2,r2 / search parent process table 
  2746                              <1> 		          ; / for dying process's name
  2747 00003C2C 66398B[D66B0000]    <1> 	cmp	[ebx+p.ppid-2], cx
  2748                              <1> 		; cmp p.ppid-2(r2),r3 / found it?
  2749 00003C33 7513                <1> 	jne	short sysexit_4
  2750                              <1> 		; bne 3f / no
  2751                              <1> 	;shr	bx, 1
  2752 00003C35 D0EB                <1> 	shr	bl, 1
  2753                              <1> 		; asr r2 / yes, it is a parent
  2754 00003C37 80BB[176C0000]03    <1> 	cmp	byte [ebx+p.stat-1], 3 ; SZOMB, 05/02/2014
  2755                              <1> 		; cmpb p.stat-1(r2),$3 / is the child of this 
  2756                              <1> 				     ; / dying process a zombie
  2757 00003C3E 7506                <1> 	jne	short sysexit_3 
  2758                              <1> 		; bne 2f / no
  2759 00003C40 88A3[176C0000]      <1> 	mov	[ebx+p.stat-1], ah ; 0, SFREE, 05/02/2014
  2760                              <1> 		; clrb p.stat-1(r2) / yes, free the child process
  2761                              <1> sysexit_3: ; 2:
  2762                              <1> 	;shr	bx, 1
  2763 00003C46 D0E3                <1> 	shl	bl, 1
  2764                              <1> 		; asl r2
  2765                              <1> sysexit_4: ; 3:
  2766                              <1> 		; / search the process name table 
  2767                              <1> 		; / for the dying process's parent
  2768 00003C48 663993[B66B0000]    <1> 	cmp	[ebx+p.pid-2], dx ; 17/09/2013	
  2769                              <1> 		; cmp p.pid-2(r2),r4 / found it?
  2770 00003C4F 7502                <1> 	jne	short sysexit_5
  2771                              <1> 		; bne 3f / no
  2772 00003C51 89DE                <1> 	mov	esi, ebx
  2773                              <1> 		; mov r2,r5 / yes, put index to p.pid table (parents
  2774                              <1> 		          ; / process # x2) in r5
  2775                              <1> sysexit_5: ; 3:
  2776                              <1> 	;cmp	bx, nproc + nproc
  2777 00003C53 80FB20              <1> 	cmp	bl, nproc + nproc
  2778                              <1> 		; cmp r2,$nproc+nproc / has whole table been searched?
  2779 00003C56 72D1                <1> 	jb	short sysexit_2
  2780                              <1> 		; blt 1b / no, go back
  2781                              <1> 		; mov r5,r1 / yes, r1 now has parents process # x2
  2782 00003C58 21F6                <1> 	and	esi, esi ; r5=r1
  2783 00003C5A 7431                <1> 	jz	short sysexit_6
  2784                              <1> 		; beq 2f / no parent has been found. 
  2785                              <1> 		       ; / The process just dies
  2786 00003C5C 66D1EE              <1> 	shr	si, 1
  2787                              <1> 		; asr r1 / set up index to p.stat
  2788 00003C5F 8A86[176C0000]      <1> 	mov	al, [esi+p.stat-1]
  2789                              <1> 		; movb p.stat-1(r1),r2 / move status of parent to r2
  2790 00003C65 20C0                <1> 	and	al, al
  2791 00003C67 7424                <1> 	jz	short sysexit_6
  2792                              <1> 		; beq 2f / if its been freed, 2f
  2793 00003C69 3C03                <1> 	cmp	al, 3
  2794                              <1> 		; cmp r2,$3 / is parent a zombie?
  2795 00003C6B 7420                <1> 	je	short sysexit_6
  2796                              <1> 		; beq 2f / yes, 2f
  2797                              <1> 	; BH = 0
  2798 00003C6D 8A1D[E76E0000]      <1> 	mov	bl, [u.uno]
  2799                              <1> 		; movb u.uno,r3 / move dying process's number to r3
  2800 00003C73 C683[176C0000]03    <1> 	mov	byte [ebx+p.stat-1], 3  ; SZOMB, 05/02/2014
  2801                              <1> 		; movb $3,p.stat-1(r3) / make the process a zombie
  2802                              <1> 	; 05/02/2014
  2803 00003C7A 3C01                <1> 	cmp	al, 1 ; SRUN
  2804 00003C7C 740F                <1> 	je	short sysexit_6
  2805                              <1> 	;cmp	al, 2
  2806                              <1> 		; cmp r2,$2 / is the parent waiting for 
  2807                              <1> 			  ; / this child to die
  2808                              <1> 	;jne	short sysexit_6	
  2809                              <1> 		; bne 2f / yes, notify parent not to wait any more
  2810                              <1> 	; 05/02/2014
  2811                              <1> 	; p.stat = 2 --> waiting
  2812                              <1> 	; p.stat = 4 --> sleeping
  2813 00003C7E C686[176C0000]01    <1> 	mov	byte [esi+p.stat-1], 1 ; SRUN ; 05/02/2014
  2814                              <1> 	;dec	byte [esi+p.stat-1]
  2815                              <1> 		; decb	p.stat-1(r1) / awaken it by putting it (parent)
  2816 00003C85 6689F0              <1> 	mov	ax, si ; r1  (process number in AL)
  2817                              <1> 	; 
  2818                              <1> 	;mov	ebx, runq + 4
  2819                              <1> 		; mov $runq+4,r2 / on the runq
  2820 00003C88 E87A120000          <1> 	call	putlu
  2821                              <1> 		; jsr r0, putlu
  2822                              <1> sysexit_6: ; 2:
  2823                              <1> 	; 31/08/2015
  2824                              <1> 		; / the process dies
  2825 00003C8D C605[E76E0000]00    <1> 	mov	byte [u.uno], 0
  2826                              <1> 		; clrb u.uno / put zero as the process number, 
  2827                              <1> 	           ; / so "swap" will
  2828 00003C94 E8A1110000          <1> 	call	swap
  2829                              <1> 		; jsr r0,swap / overwrite process with another process
  2830                              <1> hlt_sys:
  2831                              <1> 	;sti ; 18/01/2014
  2832                              <1> hlts0:
  2833 00003C99 F4                  <1> 	hlt
  2834 00003C9A EBFD                <1> 	jmp	short hlts0
  2835                              <1> 		; 0 / and thereby kill it; halt?
  2836                              <1> 
  2837                              <1> 
  2838                              <1> syswait: ; < wait for a processs to die >
  2839                              <1> 	; 09/02/2022
  2840                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2841                              <1> 	; 17/09/2015
  2842                              <1> 	; 02/09/2015
  2843                              <1> 	; 01/09/2015
  2844                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - Beginning)
  2845                              <1> 	; 24/05/2013 - 05/02/2014 (Retro UNIX 8086 v1)
  2846                              <1> 	;
  2847                              <1> 	; 'syswait' waits for a process die. 
  2848                              <1> 	; It works in following way:
  2849                              <1> 	;    1) From the parent process number, the parent's 
  2850                              <1> 	; 	process name is found. The p.ppid table of parent
  2851                              <1> 	;	names is then searched for this process name.
  2852                              <1> 	;	If a match occurs, r2 contains child's process
  2853                              <1> 	;	number. The child status is checked to see if it is
  2854                              <1> 	;	a zombie, i.e; dead but not waited for (p.stat=3)
  2855                              <1> 	;	If it is, the child process is freed and it's name
  2856                              <1> 	;	is put in (u.r0). A return is then made via 'sysret'.
  2857                              <1> 	;	If the child is not a zombie, nothing happens and
  2858                              <1> 	;	the search goes on through the p.ppid table until
  2859                              <1> 	;	all processes are checked or a zombie is found.
  2860                              <1> 	;    2) If no zombies are found, a check is made to see if
  2861                              <1> 	;	there are any children at all. If there are none,
  2862                              <1> 	;	an error return is made. If there are, the parent's
  2863                              <1> 	;	status is set to 2 (waiting for child to die),
  2864                              <1> 	;	the parent is swapped out, and a branch to 'syswait'
  2865                              <1> 	;	is made to wait on the next process.
  2866                              <1> 	;
  2867                              <1> 	; Calling sequence:
  2868                              <1> 	;	?
  2869                              <1> 	; Arguments:
  2870                              <1> 	;	-
  2871                              <1> 	; Inputs: - 
  2872                              <1> 	; Outputs: if zombie found, it's name put in u.r0.	
  2873                              <1> 	; ...............................................................
  2874                              <1> 	;				
  2875                              <1> 	
  2876                              <1> ; / wait for a process to die
  2877                              <1> 
  2878                              <1> syswait_0:
  2879 00003C9C 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; 01/09/2015
  2880                              <1> 		; movb u.uno,r1 / put parents process number in r1
  2881 00003CA3 D0E3                <1> 	shl	bl, 1
  2882                              <1> 	;shl	bx, 1
  2883                              <1> 		; asl r1 / x2 to get index into p.pid table
  2884 00003CA5 668B83[B66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  2885                              <1> 		; mov p.pid-2(r1),r1 / get the name of this process
  2886 00003CAC 31F6                <1> 	xor	esi, esi
  2887                              <1> 		; clr r2
  2888 00003CAE 31C9                <1> 	xor	ecx, ecx ; 30/10/2013
  2889                              <1> 	;xor 	cl, cl
  2890                              <1> 		; clr r3 / initialize reg 3
  2891                              <1> syswait_1: ; 1:
  2892                              <1> 	; 09/02/2022
  2893 00003CB0 46                  <1> 	inc	esi
  2894 00003CB1 46                  <1> 	inc	esi
  2895                              <1> 	;add	si, 2
  2896                              <1> 		; add $2,r2 / use r2 for index into p.ppid table
  2897                              <1> 			  ; / search table of parent processes 
  2898                              <1> 			  ; / for this process name
  2899 00003CB2 663B86[D66B0000]    <1> 	cmp	ax, [esi+p.ppid-2]
  2900                              <1> 		; cmp p.ppid-2(r2),r1 / r2 will contain the childs 
  2901                              <1> 			            ; / process number
  2902 00003CB9 7531                <1> 	jne	short syswait_3
  2903                              <1> 		;bne 3f / branch if no match of parent process name
  2904                              <1> 	;inc	cx
  2905 00003CBB FEC1                <1> 	inc	cl
  2906                              <1> 		;inc r3 / yes, a match, r3 indicates number of children
  2907                              <1> 	; 09/02/2022
  2908 00003CBD D1EE                <1> 	shr	esi, 1
  2909                              <1> 	;shr	si, 1
  2910                              <1> 		; asr r2 / r2/2 to get index to p.stat table
  2911                              <1> 	; The possible states ('p.stat' values) of a process are:
  2912                              <1> 	;	0 = free or unused
  2913                              <1> 	;	1 = active
  2914                              <1> 	;	2 = waiting for a child process to die
  2915                              <1> 	;	3 = terminated, but not yet waited for (zombie).	
  2916 00003CBF 80BE[176C0000]03    <1> 	cmp	byte [esi+p.stat-1], 3 ; SZOMB, 05/02/2014
  2917                              <1> 		; cmpb p.stat-1(r2),$3 / is the child process a zombie?
  2918 00003CC6 7522                <1> 	jne	short syswait_2
  2919                              <1> 		; bne 2f / no, skip it
  2920 00003CC8 88BE[176C0000]      <1> 	mov	[esi+p.stat-1], bh ; 0
  2921                              <1> 		; clrb p.stat-1(r2) / yes, free it
  2922                              <1> 	; 09/02/2022
  2923 00003CCE D1E6                <1> 	shl	esi, 1
  2924                              <1> 	;shl	si, 1
  2925                              <1> 		; asl r2 / r2x2 to get index into p.pid table
  2926 00003CD0 0FB786[B66B0000]    <1> 	movzx	eax, word [esi+p.pid-2]
  2927 00003CD7 A3[986E0000]        <1> 	mov	[u.r0], eax
  2928                              <1> 		; mov p.pid-2(r2),*u.r0 
  2929                              <1> 			      ; / put childs process name in (u.r0)
  2930                              <1> 	;
  2931                              <1> 	; Retro UNIX 386 v1 modification ! (17/09/2015)
  2932                              <1> 	;
  2933                              <1> 	; Parent process ID -p.ppid- field (of the child process)
  2934                              <1> 	; must be cleared in order to prevent infinitive 'syswait'
  2935                              <1> 	; system call loop from the application/program if it calls
  2936                              <1> 	; 'syswait' again (mistakenly) while there is not a zombie
  2937                              <1> 	; or running child process to wait. ('forktest.s', 17/09/2015)
  2938                              <1> 	;
  2939                              <1> 	; Note: syswait will return with error if there is not a
  2940                              <1> 	;       zombie or running process to wait.	
  2941                              <1> 	;
  2942                              <1> 	;sub	ax, ax
  2943                              <1> 	; 08/01/2022
  2944 00003CDC 29C0                <1> 	sub	eax, eax
  2945 00003CDE 668986[D66B0000]    <1> 	mov 	[esi+p.ppid-2], ax ; 0 ; 17/09/2015
  2946 00003CE5 E90AFEFFFF          <1> 	jmp	sysret0 ; ax = 0
  2947                              <1> 	;
  2948                              <1> 	;jmp	sysret
  2949                              <1> 		; br sysret1 / return cause child is dead
  2950                              <1> syswait_2: ; 2:
  2951                              <1> 	; 09/02/2022
  2952 00003CEA D1E6                <1> 	shl	esi, 1
  2953                              <1> 	;shl	si, 1
  2954                              <1> 		; asl r2 / r2x2 to get index into p.ppid table
  2955                              <1> syswait_3: ; 3:
  2956 00003CEC 6683FE20            <1> 	cmp	si, nproc+nproc
  2957                              <1> 		; cmp r2,$nproc+nproc / have all processes been checked?
  2958 00003CF0 72BE                <1> 	jb	short syswait_1
  2959                              <1> 		; blt 1b / no, continue search
  2960                              <1> 	;and	cx, cx
  2961 00003CF2 20C9                <1> 	and	cl, cl
  2962                              <1> 		; tst r3 / one gets here if there are no children 
  2963                              <1> 		       ; / or children that are still active
  2964                              <1> 	; 30/10/2013
  2965 00003CF4 7515                <1> 	jnz	short syswait_4
  2966                              <1> 	;jz	error
  2967                              <1> 		; beq error1 / there are no children, error
  2968 00003CF6 890D[986E0000]      <1> 	mov	[u.r0], ecx ; 0
  2969                              <1> 	; 09/02/2022
  2970 00003CFC C705[ED6E0000]1B00- <1> 	mov	dword [u.error], ERR_MISC ; 27
  2970 00003D04 0000                <1>
  2971                              <1> 			; miscellaneous/other errors
  2972 00003D06 E9C7FDFFFF          <1> 	jmp	error
  2973                              <1> syswait_4:
  2974 00003D0B 8A1D[E76E0000]      <1> 	mov	bl, [u.uno]
  2975                              <1> 		; movb u.uno,r1 / there are children so put 
  2976                              <1> 			      ; / parent process number in r1
  2977 00003D11 FE83[176C0000]      <1> 	inc	byte [ebx+p.stat-1] ; 2, SWAIT, 05/02/2014
  2978                              <1> 		; incb p.stat-1(r1) / it is waiting for 
  2979                              <1> 				  ; / other children to die
  2980                              <1> 	; 04/11/2013
  2981 00003D17 E81E110000          <1> 	call	swap
  2982                              <1> 		; jsr r0,swap / swap it out, because it's waiting
  2983 00003D1C E97BFFFFFF          <1> 	jmp	syswait_0
  2984                              <1> 		; br syswait / wait on next process
  2985                              <1> 
  2986                              <1> sysfork: ; < create a new process >
  2987                              <1> 	; 26/02/2022
  2988                              <1> 	; 25/02/2022
  2989                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1)
  2990                              <1> 	; 18/09/2015
  2991                              <1> 	; 04/09/2015
  2992                              <1> 	; 02/09/2015
  2993                              <1> 	; 01/09/2015
  2994                              <1> 	; 28/08/2015
  2995                              <1> 	; 14/05/2015
  2996                              <1> 	; 10/05/2015
  2997                              <1> 	; 09/05/2015
  2998                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 - Beginning)
  2999                              <1> 	; 24/05/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  3000                              <1> 	;
  3001                              <1> 	; 'sysfork' creates a new process. This process is referred
  3002                              <1> 	; to as the child process. This new process core image is
  3003                              <1> 	; a copy of that of the caller of 'sysfork'. The only
  3004                              <1> 	; distinction is the return location and the fact that (u.r0)
  3005                              <1> 	; in the old process (parent) contains the process id (p.pid)
  3006                              <1> 	; of the new process (child). This id is used by 'syswait'.
  3007                              <1> 	; 'sysfork' works in the following manner: 	
  3008                              <1> 	;    1) The process status table (p.stat) is searched to find
  3009                              <1> 	;	a process number that is unused. If none are found
  3010                              <1> 	;	an error occurs.
  3011                              <1> 	;    2) when one is found, it becomes the child process number
  3012                              <1> 	;	and it's status (p.stat) is set to active.
  3013                              <1> 	;    3) If the parent had a control tty, the interrupt 
  3014                              <1> 	;	character in that tty buffer is cleared.
  3015                              <1> 	;    4) The child process is put on the lowest priority run 
  3016                              <1> 	;	queue via 'putlu'.
  3017                              <1> 	;    5) A new process name is gotten from 'mpid' (actually 
  3018                              <1> 	;	it is a unique number) and is put in the child's unique
  3019                              <1> 	;	identifier; process id (p.pid).
  3020                              <1> 	;    6) The process name of the parent is then obtained and
  3021                              <1> 	;	placed in the unique identifier of the parent process
  3022                              <1> 	;	name is then put in 'u.r0'.	
  3023                              <1> 	;    7) The child process is then written out on disk by
  3024                              <1> 	;	'wswap',i.e., the parent process is copied onto disk
  3025                              <1> 	;	and the child is born. (The child process is written 
  3026                              <1> 	;	out on disk/drum with 'u.uno' being the child process
  3027                              <1> 	;	number.)
  3028                              <1> 	;    8) The parent process number is then restored to 'u.uno'.
  3029                              <1> 	;    9) The child process name is put in 'u.r0'.
  3030                              <1> 	;   10) The pc on the stack sp + 18 is incremented by 2 to
  3031                              <1> 	;	create the return address for the parent process.
  3032                              <1> 	;   11) The 'u.fp' list as then searched to see what files
  3033                              <1> 	;	the parent has opened. For each file the parent has
  3034                              <1> 	;	opened, the corresponding 'fsp' entry must be updated
  3035                              <1> 	;	to indicate that the child process also has opened
  3036                              <1> 	;	the file. A branch to 'sysret' is then made.	 			 				
  3037                              <1> 	;
  3038                              <1> 	; Calling sequence:
  3039                              <1> 	;	from shell ?
  3040                              <1> 	; Arguments:
  3041                              <1> 	;	-
  3042                              <1> 	; Inputs: -
  3043                              <1> 	; Outputs: *u.r0 - child process name
  3044                              <1> 	; ...............................................................
  3045                              <1> 	;	
  3046                              <1> 	; Retro UNIX 8086 v1 modification: 
  3047                              <1> 	;	AX = r0 = PID (>0) (at the return of 'sysfork')
  3048                              <1> 	;	= process id of child a parent process returns
  3049                              <1> 	;	= process id of parent when a child process returns
  3050                              <1> 	;
  3051                              <1> 	;       In original UNIX v1, sysfork is called and returns as
  3052                              <1> 	;	in following manner: (with an example: c library, fork)
  3053                              <1> 	;	
  3054                              <1> 	;	1:
  3055                              <1> 	;		sys	fork
  3056                              <1> 	;			br 1f  / child process returns here
  3057                              <1> 	;		bes	2f     / parent process returns here
  3058                              <1> 	;		/ pid of new process in r0
  3059                              <1> 	;		rts	pc
  3060                              <1> 	;	2: / parent process condionally branches here
  3061                              <1> 	;		mov	$-1,r0 / pid = -1 means error return
  3062                              <1> 	;		rts	pc
  3063                              <1> 	;
  3064                              <1> 	;	1: / child process brances here
  3065                              <1> 	;		clr	r0   / pid = 0 in child process
  3066                              <1> 	;		rts	pc
  3067                              <1> 	;
  3068                              <1> 	;	In UNIX v7x86 (386) by Robert Nordier (1999)
  3069                              <1> 	;		// pid = fork();
  3070                              <1> 	;		//
  3071                              <1> 	;		// pid == 0 in child process; 
  3072                              <1> 	;		// pid == -1 means error return
  3073                              <1> 	;		// in child, 
  3074                              <1> 	;		//	parents id is in par_uid if needed
  3075                              <1> 	;		
  3076                              <1> 	;		_fork:
  3077                              <1> 	;			mov	$.fork,eax
  3078                              <1> 	;			int	$0x30
  3079                              <1> 	;			jmp	1f
  3080                              <1> 	;			jnc	2f
  3081                              <1> 	;			jmp	cerror
  3082                              <1> 	;		1:
  3083                              <1> 	;			mov	eax,_par_uid
  3084                              <1> 	;			xor	eax,eax
  3085                              <1> 	;		2:
  3086                              <1> 	;			ret
  3087                              <1> 	;
  3088                              <1> 	;	In Retro UNIX 8086 v1,
  3089                              <1> 	;	'sysfork' returns in following manner:
  3090                              <1> 	;	
  3091                              <1> 	;		mov	ax, sys_fork
  3092                              <1> 	;		mov	bx, offset @f ; routine for child
  3093                              <1> 	;		int	20h
  3094                              <1> 	;		jc	error
  3095                              <1> 	;		
  3096                              <1> 	;	; Routine for parent process here (just after 'jc')
  3097                              <1> 	;		mov	word ptr [pid_of_child], ax
  3098                              <1> 	;		jmp	next_routine_for_parent	
  3099                              <1> 	;
  3100                              <1> 	;	@@: ; routine for child process here				
  3101                              <1> 	;		....	
  3102                              <1> 	;	NOTE: 'sysfork' returns to specified offset
  3103                              <1> 	;	       for child process by using BX input.
  3104                              <1> 	;	      (at first, parent process will return then 
  3105                              <1> 	;	      child process will return -after swapped in-
  3106                              <1> 	;	      'syswait' is needed in parent process
  3107                              <1> 	;	      if return from child process will be waited for.)
  3108                              <1> 	;	  				
  3109                              <1> 	
  3110                              <1> ; / create a new process
  3111                              <1> 	; EBX = return address for child process 
  3112                              <1> 	     ; (Retro UNIX 8086 v1 modification !)
  3113 00003D21 31F6                <1> 	xor 	esi, esi
  3114                              <1> 		; clr r1
  3115                              <1> sysfork_1: ; 1: / search p.stat table for unused process number
  3116 00003D23 46                  <1> 	inc	esi
  3117                              <1> 		; inc r1
  3118 00003D24 80BE[176C0000]00    <1> 	cmp	byte [esi+p.stat-1], 0 ; SFREE, 05/02/2014
  3119                              <1> 		; tstb p.stat-1(r1) / is process active, unused, dead
  3120 00003D2B 760B                <1> 	jna	short sysfork_2	
  3121                              <1> 		; beq 1f / it's unused so branch
  3122 00003D2D 6683FE10            <1> 	cmp	si, nproc
  3123                              <1> 		; cmp r1,$nproc / all processes checked
  3124 00003D31 72F0                <1> 	jb	short sysfork_1
  3125                              <1> 		; blt 1b / no, branch back
  3126                              <1> 	;
  3127                              <1> 	; Retro UNIX 8086 v1. modification:
  3128                              <1> 	;	Parent process returns from 'sysfork' to address 
  3129                              <1> 	;	which is just after 'sysfork' system call in parent
  3130                              <1> 	;	process. Child process returns to address which is put
  3131                              <1> 	;	in BX register by parent process for 'sysfork'. 
  3132                              <1> 	;
  3133                              <1> 		;add $2,18.(sp) / add 2 to pc when trap occured, points
  3134                              <1> 		             ; / to old process return
  3135                              <1> 		; br error1 / no room for a new process
  3136                              <1> sysfork_0:
  3137 00003D33 E99AFDFFFF          <1> 	jmp	error
  3138                              <1> sysfork_2: ; 1:
  3139 00003D38 E879F0FFFF          <1> 	call	allocate_page
  3140                              <1> 	;jc	error
  3141                              <1> 	; 08/01/2022
  3142 00003D3D 72F4                <1> 	jc	short sysfork_0
  3143                              <1> 
  3144 00003D3F 50                  <1> 	push	eax   ; UPAGE (user structure page) address
  3145                              <1> 	; Retro UNIX 386 v1 modification!
  3146 00003D40 E86AF2FFFF          <1> 	call	duplicate_page_dir
  3147                              <1> 		; EAX = New page directory 
  3148 00003D45 7308                <1> 	jnc	short sysfork_3
  3149 00003D47 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3150 00003D48 E831F2FFFF          <1> 	call 	deallocate_page
  3151                              <1> 	;jmp	error
  3152                              <1> 	; 08/01/2022
  3153 00003D4D EBE4                <1> 	jmp	short sysfork_0 ; error
  3154                              <1> sysfork_3:
  3155                              <1> 	; Retro UNIX 386 v1 modification !
  3156 00003D4F 56                  <1> 	push	esi
  3157 00003D50 E85C110000          <1> 	call	wswap ; save current user (u) structure, user registers
  3158                              <1> 		      ; and interrupt return components (for IRET)
  3159 00003D55 8705[F16E0000]      <1> 	xchg	eax, [u.pgdir] ; page directory of the child process
  3160 00003D5B A3[F56E0000]        <1> 	mov	[u.ppgdir], eax ; page directory of the parent process
  3161 00003D60 5E                  <1> 	pop	esi
  3162 00003D61 58                  <1> 	pop	eax   ; UPAGE (user structure page) address
  3163                              <1> 		; [u.usp] = esp
  3164 00003D62 89F7                <1> 	mov	edi, esi
  3165                              <1> 	;shl	di, 2
  3166                              <1> 	; 08/01/2022
  3167 00003D64 C1E702              <1> 	shl	edi, 2
  3168 00003D67 8987[246C0000]      <1> 	mov	[edi+p.upage-4], eax ; memory page for 'user' struct
  3169 00003D6D A3[E86E0000]        <1> 	mov	[u.upage], eax ; memory page for 'user' struct (child)
  3170                              <1> 	; 28/08/2015
  3171 00003D72 0FB605[E76E0000]    <1> 	movzx	eax, byte [u.uno] ; parent process number
  3172                              <1> 		; movb u.uno,-(sp) / save parent process number
  3173 00003D79 89C7                <1> 	mov	edi, eax
  3174 00003D7B 50                  <1>         push	eax ; ** 
  3175 00003D7C 8A87[F76B0000]      <1> 	mov     al, [edi+p.ttyc-1] ; console tty (parent)
  3176                              <1> 		; 18/09/2015
  3177 00003D82 8886[F76B0000]      <1> 	mov     [esi+p.ttyc-1], al ; set child's console tty
  3178                              <1> 	; 26/02/2022 (p.waitc is not used)
  3179                              <1> 	;mov	[esi+p.waitc-1], ah ; 0 ; reset child's wait channel
  3180                              <1> 	; 25/02/2022 (BugFix)
  3181                              <1> 	;mov	[esi+p.ttyc-1], ax ; al - set child's console tty
  3182                              <1> 	;			   ; ah - reset child's wait channel	
  3183 00003D88 89F0                <1> 	mov	eax, esi
  3184 00003D8A A2[E76E0000]        <1> 	mov	[u.uno], al ; child process number
  3185                              <1> 		;movb r1,u.uno / set child process number to r1
  3186 00003D8F FE86[176C0000]      <1>         inc     byte [esi+p.stat-1] ; 1, SRUN, 05/02/2014
  3187                              <1> 		; incb p.stat-1(r1) / set p.stat entry for child 
  3188                              <1> 				; / process to active status
  3189                              <1> 		; mov u.ttyp,r2 / put pointer to parent process' 
  3190                              <1> 			      ; / control tty buffer in r2
  3191                              <1>                 ; beq 2f / branch, if no such tty assigned
  3192                              <1> 		; clrb 6(r2) / clear interrupt character in tty buffer
  3193                              <1> 	; 2:
  3194 00003D95 53                  <1> 	push	ebx  ; * return address for the child process
  3195                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3196                              <1> 	; (Retro UNIX 8086 v1 modification!)
  3197                              <1> 		; mov $runq+4,r2
  3198 00003D96 E86C110000          <1> 	call	putlu 
  3199                              <1>  		; jsr r0,putlu / put child process on lowest priority 
  3200                              <1> 			   ; / run queue
  3201                              <1> 	; 08/01/2022
  3202 00003D9B D1E6                <1> 	shl	esi, 1
  3203                              <1> 	;shl	si, 1
  3204                              <1> 		; asl r1 / multiply r1 by 2 to get index 
  3205                              <1> 		       ; / into p.pid table
  3206 00003D9D 66FF05[866E0000]    <1> 	inc	word [mpid]
  3207                              <1> 		; inc mpid / increment m.pid; get a new process name
  3208 00003DA4 66A1[866E0000]      <1> 	mov	ax, [mpid]
  3209 00003DAA 668986[B66B0000]    <1> 	mov	[esi+p.pid-2], ax
  3210                              <1> 		;mov mpid,p.pid-2(r1) / put new process name 
  3211                              <1> 				    ; / in child process' name slot
  3212 00003DB1 5A                  <1> 	pop	edx  ; * return address for the child process
  3213                              <1> 		     ; * Retro UNIX 8086 v1 feature only !	
  3214 00003DB2 5B                  <1>   	pop	ebx  ; **
  3215                              <1> 	;mov	ebx, [esp] ; ** parent process number
  3216                              <1> 		; movb (sp),r2 / put parent process number in r2
  3217                              <1> 	; 08/01/2022
  3218 00003DB3 D1E3                <1> 	shl	ebx, 1
  3219                              <1> 	;shl 	bx, 1
  3220                              <1> 		; asl r2 / multiply by 2 to get index into below tables
  3221                              <1> 	;movzx eax, word [ebx+p.pid-2]
  3222 00003DB5 668B83[B66B0000]    <1> 	mov	ax, [ebx+p.pid-2]
  3223                              <1> 		; mov p.pid-2(r2),r2 / get process name of parent
  3224                              <1> 				   ; / process
  3225 00003DBC 668986[D66B0000]    <1> 	mov	[esi+p.ppid-2], ax
  3226                              <1> 		; mov r2,p.ppid-2(r1) / put parent process name 
  3227                              <1> 			  ; / in parent process slot for child
  3228 00003DC3 A3[986E0000]        <1> 	mov	[u.r0], eax	
  3229                              <1> 		; mov r2,*u.r0 / put parent process name on stack 
  3230                              <1> 			     ; / at location where r0 was saved
  3231 00003DC8 8B2D[906E0000]      <1> 	mov 	ebp, [u.sp] ; points to return address (EIP for IRET)
  3232 00003DCE 895500              <1> 	mov	[ebp], edx ; *, CS:EIP -> EIP
  3233                              <1> 			   ; * return address for the child process
  3234                              <1> 		; mov $sysret1,-(sp) /
  3235                              <1> 		; mov sp,u.usp / contents of sp at the time when 
  3236                              <1> 			      ; / user is swapped out
  3237                              <1> 		; mov $sstack,sp / point sp to swapping stack space
  3238                              <1> 	; 04/09/2015 - 01/09/2015
  3239                              <1> 	; [u.usp] = esp
  3240 00003DD1 68[F23A0000]        <1> 	push	sysret ; ***
  3241 00003DD6 8925[946E0000]      <1> 	mov	[u.usp], esp ; points to 'sysret' address (***)
  3242                              <1> 			     ; (for child process)	
  3243 00003DDC 31C0                <1> 	xor 	eax, eax
  3244 00003DDE 66A3[C86E0000]      <1> 	mov 	[u.ttyp], ax ; 0
  3245                              <1> 	;
  3246 00003DE4 E8C8100000          <1> 	call	wswap ; Retro UNIX 8086 v1 modification !
  3247                              <1> 		;jsr r0,wswap / put child process out on drum
  3248                              <1> 		;jsr r0,unpack / unpack user stack
  3249                              <1> 		;mov u.usp,sp / restore user stack pointer
  3250                              <1> 		; tst (sp)+ / bump stack pointer
  3251                              <1> 	; Retro UNIX 386 v1 modification !
  3252 00003DE9 58                  <1> 	pop	eax ; ***
  3253                              <1> 	; 08/01/2022
  3254 00003DEA D1E3                <1> 	shl	ebx, 1
  3255                              <1> 	;shl 	bx, 1
  3256 00003DEC 8B83[246C0000]      <1> 	mov     eax, [ebx+p.upage-4] ; UPAGE address ; 14/05/2015
  3257 00003DF2 E8E3100000          <1> 	call	rswap ; restore parent process 'u' structure, 
  3258                              <1> 		      ; registers and return address (for IRET)
  3259                              <1> 		;movb (sp)+,u.uno / put parent process number in u.uno
  3260 00003DF7 0FB705[866E0000]    <1>         movzx   eax, word [mpid]
  3261 00003DFE A3[986E0000]        <1> 	mov	[u.r0], eax
  3262                              <1> 		; mov mpid,*u.r0 / put child process name on stack 
  3263                              <1> 			       ; / where r0 was saved
  3264                              <1> 		; add $2,18.(sp) / add 2 to pc on stack; gives parent
  3265                              <1> 			          ; / process return
  3266                              <1> 	;xor	ebx, ebx
  3267 00003E03 31F6                <1> 	xor     esi, esi
  3268                              <1> 		;clr r1
  3269                              <1> sysfork_4: ; 1: / search u.fp list to find the files 
  3270                              <1> 	      ; / opened by the parent process
  3271                              <1> 	; 01/09/2015
  3272                              <1> 	;xor	bh, bh
  3273                              <1> 	;mov 	bl, [esi+u.fp]
  3274 00003E05 8A86[9E6E0000]      <1> 	mov 	al, [esi+u.fp]
  3275                              <1> 		; movb u.fp(r1),r2 / get an open file for this process
  3276                              <1>         ;or	bl, bl
  3277 00003E0B 08C0                <1> 	or	al, al
  3278 00003E0D 740C                <1> 	jz	short sysfork_5	
  3279                              <1> 		; beq 2f / file has not been opened by parent, 
  3280                              <1> 		       ; / so branch
  3281 00003E0F B40A                <1> 	mov	ah, 10 ; Retro UNIX 386 v1 fsp structure size = 10 bytes
  3282 00003E11 F6E4                <1> 	mul	ah
  3283                              <1> 	;;movzx	ebx, ax
  3284                              <1> 	;mov	bx, ax
  3285 00003E13 89C3                <1> 	mov	ebx, eax ; 08/01/2022
  3286                              <1> 	;shl	bx, 3
  3287                              <1> 		; asl r2 / multiply by 8
  3288                              <1>        		; asl r2 / to get index into fsp table
  3289                              <1>        		; asl r2
  3290 00003E15 FE83[666C0000]      <1>   	inc     byte [ebx+fsp-2]
  3291                              <1> 		; incb fsp-2(r2) / increment number of processes
  3292                              <1> 			     ; / using file, because child will now be
  3293                              <1> 			     ; / using this file
  3294                              <1> sysfork_5: ; 2:
  3295 00003E1B 46                  <1>         inc     esi
  3296                              <1> 		; inc r1 / get next open file
  3297 00003E1C 6683FE0A            <1>         cmp     si, 10
  3298                              <1> 		; cmp r1,$10. / 10. files is the maximum number which
  3299                              <1> 			  ; / can be opened
  3300 00003E20 72E3                <1> 	jb	short sysfork_4	
  3301                              <1> 		; blt 1b / check next entry
  3302 00003E22 E9CBFCFFFF          <1> 	jmp	sysret
  3303                              <1> 		; br sysret1
  3304                              <1> 
  3305                              <1> sysread: ; < read from file >
  3306                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  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> 	; 'sysread' is given a buffer to read into and the number of
  3312                              <1> 	; characters to be read. If finds the file from the file
  3313                              <1> 	; descriptor located in *u.r0 (r0). This file descriptor
  3314                              <1> 	; is returned from a successful open call (sysopen).
  3315                              <1> 	; The i-number of file is obtained via 'rw1' and the data
  3316                              <1> 	; is read into core via 'readi'.
  3317                              <1> 	;
  3318                              <1> 	; Calling sequence:
  3319                              <1> 	;	sysread; buffer; nchars
  3320                              <1> 	; Arguments:
  3321                              <1> 	;	buffer - location of contiguous bytes where 
  3322                              <1> 	;		 input will be placed.
  3323                              <1> 	;	nchars - number of bytes or characters to be read.
  3324                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3325                              <1> 	; Outputs: *u.r0 - number of bytes read.	
  3326                              <1> 	; ...............................................................
  3327                              <1> 	;				
  3328                              <1> 	; Retro UNIX 8086 v1 modification: 
  3329                              <1> 	;       'sysread' system call has three arguments; so,
  3330                              <1> 	;	* 1st argument, file descriptor is in BX register
  3331                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3332                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3333                              <1> 	;
  3334                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3335                              <1> 	;	to the user with number of bytes read. 
  3336                              <1> 	;
  3337 00003E27 E840000000          <1> 	call	rw1
  3338                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3339                              <1> 	;	; jsr r0,rw1 / get i-number of file to be read into r1
  3340                              <1>        	; 24/12/2021
  3341 00003E2C 7239                <1> 	jc	short sysread_err
  3342 00003E2E F6C480              <1> 	test	ah, 80h
  3343                              <1> 		; tst r1 / negative i-number?
  3344 00003E31 752A                <1> 	jnz	short rw3 ; 24/12/2021
  3345                              <1> 	;jnz	error
  3346                              <1> 		; ble error1 / yes, error 1 to read
  3347                              <1> 			   ; / it should be positive
  3348 00003E33 E836150000          <1> 	call	readi
  3349                              <1> 		; jsr r0,readi / read data into core
  3350 00003E38 EB14                <1> 	jmp	short rw0
  3351                              <1> 		; br 1f
  3352                              <1> 
  3353                              <1> syswrite: ; < write to file >
  3354                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3355                              <1> 	; 13/05/2015
  3356                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3357                              <1> 	; 23/05/2013 (Retro UNIX 8086 v1)
  3358                              <1> 	;
  3359                              <1> 	; 'syswrite' is given a buffer to write onto an output file
  3360                              <1> 	; and the number of characters to write. If finds the file
  3361                              <1> 	; from the file descriptor located in *u.r0 (r0). This file 
  3362                              <1> 	; descriptor is returned from a successful open or create call
  3363                              <1> 	; (sysopen or syscreat). The i-number of file is obtained via
  3364                              <1> 	; 'rw1' and buffer is written on the output file via 'write'.
  3365                              <1> 	;
  3366                              <1> 	; Calling sequence:
  3367                              <1> 	;	syswrite; buffer; nchars
  3368                              <1> 	; Arguments:
  3369                              <1> 	;	buffer - location of contiguous bytes to be writtten.
  3370                              <1> 	;	nchars - number of characters to be written.
  3371                              <1> 	; Inputs: *u.r0 - file descriptor (& arguments)
  3372                              <1> 	; Outputs: *u.r0 - number of bytes written.	
  3373                              <1> 	; ...............................................................
  3374                              <1> 	;				
  3375                              <1> 	; Retro UNIX 8086 v1 modification: 
  3376                              <1> 	;       'syswrite' system call has three arguments; so,
  3377                              <1> 	;	* 1st argument, file descriptor is in BX register
  3378                              <1> 	;	* 2nd argument, buffer address/offset in CX register
  3379                              <1> 	;	* 3rd argument, number of bytes is in DX register
  3380                              <1> 	;
  3381                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3382                              <1> 	;	to the user with number of bytes written. 
  3383                              <1> 	;
  3384 00003E3A E82D000000          <1> 	call	rw1
  3385                              <1> 	;jc	error ; 13/05/2015, ax < 1
  3386                              <1> 	;	; jsr r0,rw1 / get i-number in r1 of file to write
  3387                              <1>        	; 24/12/2021
  3388 00003E3F 7226                <1> 	jc	short syswrite_err
  3389 00003E41 F6C480              <1>         test	ah, 80h
  3390                              <1> 		; tst r1 / positive i-number ?
  3391 00003E44 7417                <1>         jz	short rw3 ; 13/05/2015
  3392                              <1> 	;jz	error
  3393                              <1> 		; bge error1 / yes, error 1 
  3394                              <1> 			   ; / negative i-number means write
  3395 00003E46 66F7D8              <1>         neg	ax
  3396                              <1> 		; neg r1 / make it positive
  3397 00003E49 E80E170000          <1> 	call	writei
  3398                              <1>         	; jsr r0,writei / write data
  3399                              <1> rw0: ; 1:
  3400 00003E4E A1[C06E0000]        <1>         mov	eax, [u.nread]
  3401 00003E53 A3[986E0000]        <1> 	mov	[u.r0], eax
  3402                              <1> 		; mov u.nread,*u.r0 / put no. of bytes transferred
  3403                              <1> 				  ; / into (u.r0)
  3404 00003E58 E995FCFFFF          <1> 	jmp	sysret
  3405                              <1>         	; br sysret1
  3406                              <1> 
  3407                              <1> rw3: 
  3408                              <1> 	; 13/05/2015
  3409 00003E5D C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  3409 00003E65 0000                <1>
  3410                              <1> 	;stc
  3411                              <1> 	;retn
  3412                              <1> 	; 24/12/2021 (BugFix)
  3413                              <1> sysread_err:
  3414                              <1> syswrite_err:
  3415 00003E67 E966FCFFFF          <1> 	jmp	error
  3416                              <1> 
  3417                              <1> rw1:	
  3418                              <1> 	; 14/05/2015
  3419                              <1> 	; 13/05/2015
  3420                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3421                              <1> 	; 23/05/2013 - 24/05/2013 (Retro UNIX 8086 v1)
  3422                              <1> 	; System call registers: bx, cx, dx (through 'sysenter')
  3423                              <1> 	;
  3424                              <1> 	;mov	[u.base], ecx 	; buffer address/offset 
  3425                              <1> 				;(in the user's virtual memory space)
  3426                              <1> 	;mov	[u.count], edx 
  3427                              <1> 		; jsr r0,arg; u.base / get buffer pointer
  3428                              <1>         	; jsr r0,arg; u.count / get no. of characters
  3429                              <1> 	;;mov	eax, ebx ; file descriptor
  3430                              <1> 		; mov *u.r0,r1 / put file descriptor 
  3431                              <1> 		             ; / (index to u.fp table) in r1
  3432                              <1> 	; 13/05/2015
  3433 00003E6C C705[986E0000]0000- <1> 	mov	dword [u.r0], 0 ; r/w transfer count = 0 (reset)
  3433 00003E74 0000                <1>
  3434                              <1> 	;
  3435                              <1> 	;; call	getf
  3436                              <1>         ; eBX = File descriptor
  3437 00003E76 E8240B0000          <1> 	call	getf1 ; calling point in 'getf' from 'rw1'
  3438                              <1> 		; jsr r0,getf / get i-number of the file in r1
  3439                              <1> 	; AX = I-number of the file ; negative i-number means write
  3440                              <1> 	; 13/05/2015
  3441 00003E7B 6683F801            <1> 	cmp 	ax, 1
  3442 00003E7F 7217                <1> 	jb	short rw2
  3443                              <1> 	;
  3444 00003E81 890D[B86E0000]      <1> 	mov	[u.base], ecx 	; buffer address/offset 
  3445                              <1> 				;(in the user's virtual memory space)
  3446 00003E87 8915[BC6E0000]      <1> 	mov	[u.count], edx 
  3447                              <1> 	; 14/05/2015
  3448 00003E8D C705[ED6E0000]0000- <1>         mov     dword [u.error], 0 ; reset the last error code
  3448 00003E95 0000                <1>
  3449 00003E97 C3                  <1> 	retn
  3450                              <1>         	; rts r0
  3451                              <1> rw2:
  3452                              <1> 	; 13/05/2015
  3453 00003E98 C705[ED6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3453 00003EA0 0000                <1>
  3454 00003EA2 C3                  <1> 	retn
  3455                              <1> 
  3456                              <1> sysopen: ;<open file>
  3457                              <1> 	; 09/01/2022
  3458                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3459                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3460                              <1> 	; 22/05/2013 - 27/05/2013 (Retro UNIX 8086 v1)
  3461                              <1> 	;
  3462                              <1> 	; 'sysopen' opens a file in following manner:
  3463                              <1> 	;    1) The second argument in a sysopen says whether to
  3464                              <1> 	;	open the file ro read (0) or write (>0).
  3465                              <1> 	;    2) I-node of the particular file is obtained via 'namei'.
  3466                              <1> 	;    3) The file is opened by 'iopen'.
  3467                              <1> 	;    4) Next housekeeping is performed on the fsp table
  3468                              <1> 	;	and the user's open file list - u.fp.
  3469                              <1> 	;	a) u.fp and fsp are scanned for the next available slot.
  3470                              <1> 	;	b) An entry for the file is created in the fsp table.
  3471                              <1> 	;	c) The number of this entry is put on u.fp list.
  3472                              <1> 	;	d) The file descriptor index to u.fp list is pointed
  3473                              <1> 	;	   to by u.r0.
  3474                              <1> 	;
  3475                              <1> 	; Calling sequence:
  3476                              <1> 	;	sysopen; name; mode
  3477                              <1> 	; Arguments:
  3478                              <1> 	;	name - file name or path name
  3479                              <1> 	;	mode - 0 to open for reading
  3480                              <1> 	;	       1 to open for writing
  3481                              <1> 	; Inputs: (arguments)
  3482                              <1> 	; Outputs: *u.r0 - index to u.fp list (the file descriptor)
  3483                              <1> 	;		  is put into r0's location on the stack.	
  3484                              <1> 	; ...............................................................
  3485                              <1> 	;				
  3486                              <1> 	; Retro UNIX 8086 v1 modification: 
  3487                              <1> 	;       'sysopen' system call has two arguments; so,
  3488                              <1> 	;	* 1st argument, name is pointed to by BX register
  3489                              <1> 	;	* 2nd argument, mode is in CX register
  3490                              <1> 	;
  3491                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3492                              <1> 	;	to the user with the file descriptor/number 
  3493                              <1> 	;	(index to u.fp list).
  3494                              <1> 	;
  3495                              <1> 	;call	arg2
  3496                              <1> 	; * name - 'u.namep' points to address of file/path name
  3497                              <1> 	;          in the user's program segment ('u.segmnt')
  3498                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3499                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3500                              <1> 	;          which is on top of stack.
  3501                              <1> 	;
  3502                              <1> 	; jsr r0,arg2 / get sys args into u.namep and on stack
  3503                              <1> 	;
  3504                              <1>        	; system call registers: ebx, ecx (through 'sysenter')
  3505                              <1> 
  3506 00003EA3 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  3507                              <1> 	; 24/12/2021 (cx -> ecx)
  3508 00003EA9 51                  <1> 	push	ecx ; * 
  3509 00003EAA E8210B0000          <1> 	call	namei
  3510                              <1> 		; jsr r0,namei / i-number of file in r1
  3511                              <1>      	;and	ax, ax
  3512                              <1> 	;jz	error ; File not found
  3513 00003EAF 7239                <1> 	jc	short fnotfound ; 14/05/2015
  3514                              <1> 	;jc	error ; 27/05/2013
  3515                              <1> 		; br  error2 / file not found
  3516                              <1>    	; 24/12/2021
  3517                              <1> 	;pop	edx ; * ; mode
  3518                              <1> 	;push	edx ; *
  3519 00003EB1 8B1424              <1> 	mov	edx, [esp] ; *
  3520                              <1> 	; edx = open mode (0 or 1)
  3521                              <1> 	;or	dx, dx
  3522 00003EB4 08D2                <1> 	or	dl, dl
  3523                              <1> 		; tst (sp) / is mode = 0 (2nd arg of call; 
  3524                              <1> 		         ; / 0 means, open for read)
  3525 00003EB6 7403                <1> 	jz	short sysopen_0
  3526                              <1> 		; beq 1f / yes, leave i-number positive
  3527                              <1> syscreat_0: ; 27/12/2015
  3528 00003EB8 66F7D8              <1> 	neg	ax
  3529                              <1>         	; neg r1 / open for writing so make i-number negative
  3530                              <1> sysopen_0: ;1:
  3531 00003EBB E85E1A0000          <1> 	call	iopen
  3532                              <1> 		;jsr r0,iopen / open file whose i-number is in r1
  3533 00003EC0 5A                  <1> 	pop	edx ; * ; mode ; 24/12/2021
  3534                              <1> 	;and	dx, dx
  3535 00003EC1 20D2                <1> 	and	dl, dl
  3536                              <1>         	; tst (sp)+ / pop the stack and test the mode
  3537 00003EC3 7403                <1> 	jz	short sysopen_2
  3538                              <1>         	; beq op1 / is open for read op1
  3539                              <1> sysopen_1: ;op0:
  3540 00003EC5 66F7D8              <1> 	neg	ax
  3541                              <1>         	; neg r1 
  3542                              <1> 	;; NOTE: iopen always make i-number positive.
  3543                              <1> 	;; Here i-number becomes negative again. [22/05/2013]
  3544                              <1> sysopen_2: ;op1:
  3545 00003EC8 31F6                <1>         xor     esi, esi
  3546                              <1>         	; clr r2 / clear registers
  3547 00003ECA 31DB                <1>         xor     ebx, ebx
  3548                              <1> 		; clr r3
  3549                              <1> sysopen_3: ;1: / scan the list of entries in fsp table
  3550 00003ECC 389E[9E6E0000]      <1>         cmp     [esi+u.fp], bl ; 0
  3551                              <1> 		; tstb u.fp(r2) / test the entry in the u.fp list
  3552 00003ED2 7625                <1>         jna      short sysopen_4
  3553                              <1> 		; beq 1f / if byte in list is 0 branch
  3554 00003ED4 46                  <1>         inc     esi
  3555                              <1> 		; inc r2 / bump r2 so next byte can be checked
  3556 00003ED5 6683FE0A            <1>         cmp     si, 10  ; OPENFILES
  3557                              <1> 		; cmp r2,$10. / reached end of list?
  3558 00003ED9 72F1                <1> 	jb	short sysopen_3
  3559                              <1> 		; blt 1b / no, go back
  3560                              <1> toomanyf:
  3561                              <1> 	; 14/05/2015
  3562 00003EDB C705[ED6E0000]0D00- <1> 	mov	dword [u.error], ERR_TOO_MANY_FILES ; too many open files !
  3562 00003EE3 0000                <1>
  3563 00003EE5 E9E8FBFFFF          <1> 	jmp	error
  3564                              <1>         	; br error2 / yes, error (no files open)
  3565                              <1> fnotfound: 
  3566                              <1> 	; 14/05/2015
  3567 00003EEA C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; file not found !
  3567 00003EF2 0000                <1>
  3568 00003EF4 E9D9FBFFFF          <1> 	jmp	error
  3569                              <1> 
  3570                              <1> sysopen_4: ; 1:
  3571 00003EF9 6683BB[686C0000]00  <1>         cmp     word [ebx+fsp], 0
  3572                              <1> 		; tst fsp(r3) / scan fsp entries
  3573 00003F01 760D                <1>         jna     short sysopen_5
  3574                              <1> 		; beq 1f / if 0 branch
  3575                              <1> 	; 14/05/2015 - Retro UNIX 386 v1 modification !
  3576 00003F03 6683C30A            <1>         add     bx, 10 ; fsp structure size = 10 bytes/entry
  3577                              <1> 		; add $8.,r3 / add 8 to r3 
  3578                              <1> 			; / to bump it to next entry mfsp table
  3579 00003F07 6681FBF401          <1>         cmp     bx, nfiles*10
  3580                              <1> 		; cmp r3,$[nfiles*8.] / done scanning
  3581 00003F0C 72EB                <1> 	jb	short sysopen_4
  3582                              <1>        		; blt 1b / no, back
  3583                              <1> 	;jmp	error
  3584                              <1>         ;	; br error2 / yes, error
  3585                              <1> 	; 24/12/2021
  3586 00003F0E EBCB                <1> 	jmp	short toomanyf
  3587                              <1> 
  3588                              <1> sysopen_5: ; 1: / r2 has index to u.fp list; r3, has index to fsp table
  3589 00003F10 668983[686C0000]    <1>         mov     [ebx+fsp], ax
  3590                              <1> 		; mov r1,fsp(r3) / put i-number of open file 
  3591                              <1> 			; / into next available entry in fsp table,
  3592                              <1> 	; 09/01/2022
  3593                              <1> 	;mov	di, [cdev] ; word ? byte ?
  3594                              <1>         ;mov	[ebx+fsp+2], di ; device number
  3595                              <1> 		; mov cdev,fsp+2(r3) / put # of device in next word
  3596                              <1> 	;xor	edi, edi
  3597                              <1>         ;mov	[ebx+fsp+4], edi ; offset pointer (0)
  3598                              <1> 	;	; clr fsp+4(r3)
  3599                              <1>         ;mov	[ebx+fsp+8], di ; open count (0), deleted flag (0)
  3600                              <1>        	;	; clr fsp+6(r3) / clear the next two words
  3601 00003F17 31C0                <1> 	xor	eax, eax
  3602 00003F19 8983[6C6C0000]      <1> 	mov	[ebx+fsp+4], eax ; offset pointer (0)
  3603 00003F1F 668983[706C0000]    <1> 	mov	[ebx+fsp+8], ax ; open count (0), deleted flag (0)
  3604                              <1> 
  3605 00003F26 A0[7F6E0000]        <1> 	mov	al, [cdev]
  3606 00003F2B 668983[6A6C0000]    <1> 	mov	[ebx+fsp+2], ax ; device number
  3607                              <1> 
  3608 00003F32 89D8                <1>   	mov	eax, ebx
  3609 00003F34 B30A                <1> 	mov	bl, 10
  3610 00003F36 F6F3                <1> 	div	bl 
  3611                              <1> 		; asr r3
  3612                              <1> 		; asr r3 / divide by 8 
  3613                              <1> 		; asr r3 ; / to get number of the fsp entry-1
  3614 00003F38 FEC0                <1> 	inc	al
  3615                              <1>         	; inc r3 / add 1 to get fsp entry number
  3616 00003F3A 8886[9E6E0000]      <1>         mov     [esi+u.fp], al
  3617                              <1> 		; movb r3,u.fp(r2) / move entry number into 
  3618                              <1> 			; / next available slot in u.fp list
  3619 00003F40 8935[986E0000]      <1>         mov     [u.r0], esi
  3620                              <1> 		; mov r2,*u.r0 / move index to u.fp list 
  3621                              <1> 			     ; / into r0 loc on stack
  3622 00003F46 E9A7FBFFFF          <1>         jmp	sysret
  3623                              <1> 		; br sysret2
  3624                              <1> 
  3625                              <1> 	;
  3626                              <1> 	; 'fsp' table (10 bytes/entry)
  3627                              <1> 	; bit 15				   bit 0
  3628                              <1> 	; ---|-------------------------------------------
  3629                              <1> 	; r/w|		i-number of open file
  3630                              <1> 	; ---|-------------------------------------------
  3631                              <1> 	;		   device number
  3632                              <1> 	; -----------------------------------------------
  3633                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3634                              <1> 	; -----------------------------------------------
  3635                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3636                              <1> 	; ----------------------|------------------------
  3637                              <1> 	;  flag that says file 	| number of processes
  3638                              <1> 	;   has been deleted	| that have file open 
  3639                              <1> 	; ----------------------|------------------------
  3640                              <1> 	;
  3641                              <1> 
  3642                              <1> syscreat: ; < create file >
  3643                              <1> 	; 24/12/2021
  3644                              <1> 	; 27/12/2015 (Retro UNIX 386 v1.1)
  3645                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3646                              <1> 	; 27/05/2013 (Retro UNIX 8086 v1)
  3647                              <1> 	;
  3648                              <1> 	; 'syscreat' called with two arguments; name and mode.
  3649                              <1> 	; u.namep points to name of the file and mode is put
  3650                              <1> 	; on the stack. 'namei' is called to get i-number of the file.		
  3651                              <1> 	; If the file aready exists, it's mode and owner remain 
  3652                              <1> 	; unchanged, but it is truncated to zero length. If the file
  3653                              <1> 	; did not exist, an i-node is created with the new mode via
  3654                              <1> 	; 'maknod' whether or not the file already existed, it is
  3655                              <1> 	; open for writing. The fsp table is then searched for a free
  3656                              <1> 	; entry. When a free entry is found, proper data is placed
  3657                              <1> 	; in it and the number of this entry is put in the u.fp list.
  3658                              <1> 	; The index to the u.fp (also know as the file descriptor)
  3659                              <1> 	; is put in the user's r0. 			
  3660                              <1> 	;
  3661                              <1> 	; Calling sequence:
  3662                              <1> 	;	syscreate; name; mode
  3663                              <1> 	; Arguments:
  3664                              <1> 	;	name - name of the file to be created
  3665                              <1> 	;	mode - mode of the file to be created
  3666                              <1> 	; Inputs: (arguments)
  3667                              <1> 	; Outputs: *u.r0 - index to u.fp list 
  3668                              <1> 	;		   (the file descriptor of new file)
  3669                              <1> 	; ...............................................................
  3670                              <1> 	;				
  3671                              <1> 	; Retro UNIX 8086 v1 modification: 
  3672                              <1> 	;       'syscreate' system call has two arguments; so,
  3673                              <1> 	;	* 1st argument, name is pointed to by BX register
  3674                              <1> 	;	* 2nd argument, mode is in CX register
  3675                              <1> 	;
  3676                              <1> 	;	AX register (will be restored via 'u.r0') will return
  3677                              <1> 	;	to the user with the file descriptor/number 
  3678                              <1> 	;	(index to u.fp list).
  3679                              <1> 	;
  3680                              <1> 	;call	arg2
  3681                              <1> 	; * name - 'u.namep' points to address of file/path name
  3682                              <1> 	;          in the user's program segment ('u.segmnt')
  3683                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3684                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3685                              <1> 	;          which is on top of stack.
  3686                              <1> 	;
  3687                              <1>         	; jsr r0,arg2 / put file name in u.namep put mode 
  3688                              <1> 			    ; / on stack
  3689 00003F4B 891D[B06E0000]      <1> 	mov	[u.namep], ebx ; file name address
  3690                              <1> 	;push	cx ; mode
  3691                              <1> 	; 24/12/2021
  3692 00003F51 51                  <1> 	push	ecx ; cx = mode (permission flags)
  3693 00003F52 E8790A0000          <1> 	call 	namei        	
  3694                              <1> 		; jsr r0,namei / get the i-number
  3695                              <1>         ;and	ax, ax
  3696                              <1> 	;jz	short syscreat_2	       	
  3697 00003F57 721B                <1> 	jc	short syscreat_2
  3698                              <1> 		; br  2f / if file doesn't exist 2f
  3699                              <1> 	; 27/12/2015
  3700 00003F59 6683F829            <1> 	cmp	ax, 41 ; device inode ?
  3701                              <1>         ;jb	syscreat_0 ; yes
  3702                              <1> 	; 24/12/2021
  3703 00003F5D 7305                <1> 	jnb	short syscreat_1
  3704 00003F5F E954FFFFFF          <1> 	jmp	syscreat_0
  3705                              <1> syscreat_1:
  3706 00003F64 66F7D8              <1> 	neg 	ax
  3707                              <1>         	; neg r1 / if file already exists make i-number 
  3708                              <1> 		       ; / negative (open for writing)
  3709 00003F67 E8B2190000          <1> 	call	iopen
  3710                              <1>         	; jsr r0,iopen /
  3711 00003F6C E855130000          <1> 	call	itrunc
  3712                              <1>         	; jsr r0,itrunc / truncate to 0 length
  3713                              <1> 	;pop	cx ; pop mode (did not exist in original Unix v1 !?)
  3714                              <1> 	; 04/12/2021
  3715 00003F71 59                  <1> 	pop	ecx
  3716                              <1> 	; 08/01/2022
  3717 00003F72 EB0E                <1> 	jmp	short syscreat_3
  3718                              <1>         ;jmp	sysopen_1
  3719                              <1>         	; br op0
  3720                              <1> syscreat_2: ; 2: / file doesn't exist
  3721                              <1> 	;pop	ax
  3722                              <1>         ;	; mov (sp)+,r1 / put the mode in r1
  3723                              <1> 	; 24/12/2021
  3724 00003F74 58                  <1> 	pop	eax  ; ax = mode (permission flags)
  3725 00003F75 30E4                <1> 	xor	ah, ah	
  3726                              <1>         	; bic $!377,r1 / clear upper byte
  3727 00003F77 E81A0D0000          <1> 	call 	maknod
  3728                              <1>         	; jsr r0,maknod / make an i-node for this file
  3729 00003F7C 66A1[CA6E0000]      <1> 	mov	ax, [u.dirbuf]
  3730                              <1>         	; mov u.dirbuf,r1 / put i-number 
  3731                              <1> 			        ; / for this new file in r1
  3732                              <1> syscreat_3:
  3733 00003F82 E93EFFFFFF          <1>         jmp     sysopen_1
  3734                              <1>         	; br op0 / open the file
  3735                              <1> 
  3736                              <1> sysmkdir: ; < make directory >
  3737                              <1> 	; 26/02/2022
  3738                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3739                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3740                              <1> 	; 27/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3741                              <1> 	;
  3742                              <1> 	; 'sysmkdir' creates an empty directory whose name is
  3743                              <1> 	; pointed to by arg 1. The mode of the directory is arg 2.	
  3744                              <1> 	; The special entries '.' and '..' are not present.
  3745                              <1> 	; Errors are indicated if the directory already exists or		
  3746                              <1> 	; user is not the super user. 
  3747                              <1> 	;
  3748                              <1> 	; Calling sequence:
  3749                              <1> 	;	sysmkdir; name; mode
  3750                              <1> 	; Arguments:
  3751                              <1> 	;	name - points to the name of the directory
  3752                              <1> 	;	mode - mode of the directory
  3753                              <1> 	; Inputs: (arguments)
  3754                              <1> 	; Outputs: -
  3755                              <1> 	;    (sets 'directory' flag to 1; 
  3756                              <1> 	;    'set user id on execution' and 'executable' flags to 0)
  3757                              <1> 	; ...............................................................
  3758                              <1> 	;				
  3759                              <1> 	; Retro UNIX 8086 v1 modification: 
  3760                              <1> 	;       'sysmkdir' system call has two arguments; so,
  3761                              <1> 	;	* 1st argument, name is pointed to by BX register
  3762                              <1> 	;	* 2nd argument, mode is in CX register
  3763                              <1> 	;
  3764                              <1> 		
  3765                              <1> ; / make a directory
  3766                              <1> 
  3767                              <1> 	;call	arg2
  3768                              <1> 	; * name - 'u.namep' points to address of file/path name
  3769                              <1> 	;          in the user's program segment ('u.segmnt')
  3770                              <1> 	;          with offset in BX register (as sysopen argument 1).
  3771                              <1> 	; * mode - sysopen argument 2 is in CX register 
  3772                              <1> 	;          which is on top of stack.
  3773                              <1> 
  3774                              <1> 		; jsr r0,arg2 / put file name in u.namep put mode 
  3775                              <1> 			    ; / on stack
  3776 00003F87 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  3777                              <1> 	;push	cx ; mode
  3778                              <1> 	; 24/12/2021
  3779 00003F8D 51                  <1> 	push	ecx ; cx = mode
  3780 00003F8E E83D0A0000          <1> 	call	namei
  3781                              <1>         	; jsr r0,namei / get the i-number
  3782                              <1>         	;     br .+4 / if file not found branch around error
  3783                              <1>         ;xor 	ax, ax
  3784                              <1> 	;jnz	error
  3785 00003F93 731B                <1> 	jnc	short dir_exists ; 14/05/2015
  3786                              <1> 	;jnc	error	
  3787                              <1> 		; br  error2 / directory already exists (error)
  3788 00003F95 803D[E46E0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  3789                              <1>         	;tstb u.uid / is user the super user
  3790                              <1> 	;jna	short dir_access_err ; 14/05/2015
  3791                              <1> 	;;jna	error
  3792                              <1> 	; 26/02/2022 (BugFix)
  3793 00003F9C 7721                <1> 	ja	short dir_access_err
  3794                              <1>         	;bne error2 / no, not allowed
  3795                              <1> 	;pop	ax
  3796                              <1>         ;	;mov (sp)+,r1 / put the mode in r1
  3797                              <1> 	; 24/12/2021
  3798 00003F9E 58                  <1> 	pop	eax  ; ax = mode
  3799 00003F9F 6683E0CF            <1> 	and	ax, 0FFCFh ; 1111111111001111b
  3800                              <1>         	;bic $!317,r1 / all but su and ex
  3801                              <1> 	;or	ax, 4000h ; 1011111111111111b
  3802 00003FA3 80CC40              <1> 	or	ah, 40h ; Set bit 14 to 1
  3803                              <1>         	;bis $40000,r1 / directory flag
  3804 00003FA6 E8EB0C0000          <1> 	call	maknod
  3805                              <1>         	;jsr r0,maknod / make the i-node for the directory
  3806                              <1> ;sysclose_sysret: ; 26/02/2022
  3807 00003FAB E942FBFFFF          <1> 	jmp	sysret
  3808                              <1>         	;br sysret2 /
  3809                              <1> dir_exists:
  3810                              <1> 	; 14/05/2015
  3811 00003FB0 C705[ED6E0000]0E00- <1> 	mov	dword [u.error], ERR_DIR_EXISTS ; dir. already exists !
  3811 00003FB8 0000                <1>
  3812 00003FBA E913FBFFFF          <1> 	jmp	error
  3813                              <1> dir_access_err:
  3814                              <1> 	; 14/05/2015
  3815 00003FBF C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_DIR_ACCESS ; permission denied !
  3815 00003FC7 0000                <1>
  3816 00003FC9 E904FBFFFF          <1> 	jmp	error
  3817                              <1> 
  3818                              <1> sysclose: ;<close file>
  3819                              <1> 	; 26/02/2022
  3820                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3821                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3822                              <1> 	; 22/05/2013 - 26/05/2013 (Retro UNIX 8086 v1)
  3823                              <1> 	;
  3824                              <1> 	; 'sysclose', given a file descriptor in 'u.r0', closes the
  3825                              <1> 	; associated file. The file descriptor (index to 'u.fp' list)
  3826                              <1> 	; is put in r1 and 'fclose' is called.
  3827                              <1> 	;
  3828                              <1> 	; Calling sequence:
  3829                              <1> 	;	sysclose
  3830                              <1> 	; Arguments:
  3831                              <1> 	;	-  
  3832                              <1> 	; Inputs: *u.r0 - file descriptor
  3833                              <1> 	; Outputs: -
  3834                              <1> 	; ...............................................................
  3835                              <1> 	;				
  3836                              <1> 	; Retro UNIX 8086 v1 modification:
  3837                              <1> 	;	 The user/application program puts file descriptor
  3838                              <1> 	;        in BX register as 'sysclose' system call argument.
  3839                              <1> 	; 	 (argument transfer method 1)
  3840                              <1> 
  3841                              <1> 	; / close the file
  3842                              <1> 	
  3843 00003FCE 89D8                <1> 	mov 	eax, ebx
  3844 00003FD0 E887090000          <1> 	call 	fclose
  3845                              <1> 		; mov *u.r0,r1 / move index to u.fp list into r1
  3846                              <1> 		; jsr r0,fclose / close the file
  3847                              <1>                	; br error2 / unknown file descriptor
  3848                              <1> 		; br sysret2
  3849                              <1> 	; 14/05/2015
  3850                              <1> 	;jnc	sysret
  3851                              <1> 	; 04/12/2021
  3852 00003FD5 7205                <1> 	jc	short sysclose_err
  3853 00003FD7 E916FBFFFF          <1> 	jmp	sysret
  3854                              <1> 	; 26/02/2022
  3855                              <1> 	;jnc	short sysclose_sysret
  3856                              <1> sysclose_err:
  3857 00003FDC C705[ED6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN ; file not open !
  3857 00003FE4 0000                <1>
  3858 00003FE6 E9E7FAFFFF          <1> 	jmp	error
  3859                              <1> 
  3860                              <1> sysemt:
  3861                              <1> 	; 26/02/2022
  3862                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3863                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3864                              <1> 	; 10/12/2013 - 20/04/2014 (Retro UNIX 8086 v1)
  3865                              <1> 	;
  3866                              <1> 	; Retro UNIX 8086 v1 modification: 
  3867                              <1> 	;	'Enable Multi Tasking'  system call instead 
  3868                              <1> 	;	of 'Emulator Trap' in original UNIX v1 for PDP-11.
  3869                              <1> 	;
  3870                              <1> 	; Retro UNIX 8086 v1 feature only!
  3871                              <1> 	;	Using purpose: Kernel will start without time-out
  3872                              <1> 	;	(internal clock/timer) functionality.
  3873                              <1> 	;	Then etc/init will enable clock/timer for
  3874                              <1> 	;	multi tasking. (Then it will not be disabled again
  3875                              <1> 	;	except hardware reset/restart.)
  3876                              <1> 	;
  3877                              <1> 
  3878 00003FEB 803D[E46E0000]00    <1> 	cmp	byte [u.uid], 0 ; root ?
  3879                              <1> 	;;ja	error
  3880                              <1> 	;ja	badsys ; 14/05/2015
  3881                              <1> 	; 24/12/2021
  3882 00003FF2 7605                <1> 	jna	short emt_0 
  3883 00003FF4 E98BFBFFFF          <1> 	jmp	badsys
  3884                              <1> emt_0:
  3885                              <1> 	; 24/12/2021
  3886                              <1> 	;cli
  3887 00003FF9 21DB                <1> 	and	ebx, ebx
  3888 00003FFB 7429                <1> 	jz	short emt_2
  3889                              <1> 	; Enable multi tasking -time sharing-
  3890 00003FFD B8[4F4F0000]        <1> 	mov	eax, clock
  3891                              <1> 	; 26/02/2022
  3892 00004002 BA[4C0A0000]        <1> 	mov	edx, rtci_default ; disable rtc (digital) printing
  3893                              <1> emt_1:
  3894 00004007 A3[11070000]        <1> 	mov	[x_timer], eax
  3895                              <1> 	; 26/02/2022 (Temporary)
  3896 0000400C 8915[15070000]      <1> 	mov	[x_rtci], edx
  3897 00004012 B306                <1> 	mov	bl, 6  ; timer interrupt page, video page 6
  3898 00004014 E851020000          <1> 	call	wttyc  ; clear video page
  3899 00004019 B307                <1> 	mov	bl, 7  ; rtc interrupt page, video page 7
  3900 0000401B E84A020000          <1> 	call	wttyc  ; clear video page
  3901                              <1> 	;
  3902 00004020 FB                  <1> 	sti
  3903 00004021 E9CCFAFFFF          <1> 	jmp	sysret
  3904                              <1> emt_2:
  3905                              <1> 	; Disable multi tasking -time sharing-
  3906 00004026 B8[1D070000]        <1> 	mov	eax, u_timer ; enable timer tick printing
  3907                              <1> 	; 26/02/2022
  3908 0000402B BA[530A0000]        <1> 	mov	edx, rtc_p   ; enable rtc (digital) printing
  3909                              <1> 	;
  3910 00004030 EBD5                <1> 	jmp	short emt_1
  3911                              <1> 
  3912                              <1> 	; Original UNIX v1 'sysemt' routine
  3913                              <1> ;sysemt:
  3914                              <1>         ;
  3915                              <1> 	;jsr    r0,arg; 30 / put the argument of the sysemt call 
  3916                              <1> 			 ; / in loc 30
  3917                              <1>         ;cmp    30,$core / was the argument a lower address 
  3918                              <1> 			; / than core
  3919                              <1>         ;blo    1f / yes, rtssym
  3920                              <1>         ;cmp    30,$ecore / no, was it higher than "core" 
  3921                              <1> 			; / and less than "ecore"
  3922                              <1>         ;blo    2f / yes, sysret2
  3923                              <1> ;1:
  3924                              <1>         ;mov    $rtssym,30
  3925                              <1> ;2:
  3926                              <1>         ;br     sysret2
  3927                              <1> 
  3928                              <1> sysilgins:
  3929                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  3930                              <1> 	; 03/06/2013
  3931                              <1> 	; Retro UNIX 8086 v1 modification: 
  3932                              <1> 	;	not a valid system call ! (not in use)
  3933                              <1> 	;
  3934 00004032 E94DFBFFFF          <1> 	jmp	badsys
  3935                              <1> 	;jmp	error
  3936                              <1> 	;;jmp 	sysret
  3937                              <1> 
  3938                              <1> 	; Original UNIX v1 'sysemt' routine
  3939                              <1> ;sysilgins: / calculate proper illegal instruction trap address
  3940                              <1>         ;jsr    r0,arg; 10 / take address from sysilgins call
  3941                              <1> 			  ;/ put it in loc 8.,
  3942                              <1>         ;cmp    10,$core / making it the illegal instruction 
  3943                              <1> 		       ; / trap address
  3944                              <1>         ;blo    1f / is the address a user core address?  
  3945                              <1> 		; / yes, go to 2f
  3946                              <1>         ;cmp    10,$ecore
  3947                              <1>         ;blo    2f
  3948                              <1> ;1:
  3949                              <1>         ;mov    $fpsym,10 / no, make 'fpsum' the illegal 
  3950                              <1> 		    ; / instruction trap address for the system
  3951                              <1> ;2:
  3952                              <1>         ;br     sysret2 / return to the caller via 'sysret'
  3953                              <1> 
  3954                              <1> sysmdate: ; < change the modification time of a file >
  3955                              <1> 	; 23/02/2022 (Retro UNIX 386 v1 feature/modification)
  3956                              <1> 	;	(ECX input)
  3957                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3958                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  3959                              <1> 	; 03/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  3960                              <1> 	;
  3961                              <1> 	; 'sysmdate' is given a file name. It gets inode of this 
  3962                              <1> 	; file into core. The user is checked if he is the owner 
  3963                              <1> 	; or super user. If he is neither an error occurs.
  3964                              <1> 	; 'setimod' is then called to set the i-node modification
  3965                              <1> 	; byte and the modification time, but the modification time
  3966                              <1> 	; is overwritten by whatever get put on the stack during
  3967                              <1> 	; a 'systime' system call. This calls are restricted to
  3968                              <1> 	; the super user.		
  3969                              <1> 	;
  3970                              <1> 	; Calling sequence:
  3971                              <1> 	;	sysmdate; name
  3972                              <1> 	; Arguments:
  3973                              <1> 	;	name - points to the name of file
  3974                              <1> 	; Inputs: (arguments)
  3975                              <1> 	; Outputs: -
  3976                              <1> 	; ...............................................................
  3977                              <1> 	;				
  3978                              <1> 	; Retro UNIX 8086 v1 modification: 
  3979                              <1> 	;	 The user/application program puts address 
  3980                              <1> 	;	 of the file name in BX register 
  3981                              <1> 	;	 as 'sysmdate' system call argument.
  3982                              <1> 	;
  3983                              <1> ; / change the modification time of a file
  3984                              <1> 		; jsr r0,arg; u.namep / point u.namep to the file name
  3985 00004037 891D[B06E0000]      <1>         mov	[u.namep], ebx
  3986                              <1> 	; 23/02/2022 - (Retro UNIX 386 v1 modification on unix v1 code)
  3987 0000403D 890D[206B0000]      <1> 	mov	[p_time], ecx ; save new modification time to be set 
  3988 00004043 E888090000          <1> 	call	namei
  3989                              <1> 		; jsr r0,namei / get its i-number
  3990                              <1> 	;;jc	error       
  3991                              <1> 	;	; br error2 / no, such file
  3992                              <1> 	;jc	fnotfound ; file not found !
  3993                              <1> 	; 24/12/2021
  3994 00004048 7305                <1> 	jnc	short mdate_0
  3995 0000404A E99BFEFFFF          <1> 	jmp	fnotfound
  3996                              <1> mdate_0:
  3997 0000404F E846110000          <1> 	call	iget
  3998                              <1> 		; jsr r0,iget / get i-node into core
  3999 00004054 A0[E46E0000]        <1> 	mov	al, [u.uid]
  4000 00004059 3A05[9B6B0000]      <1> 	cmp	al, [i.uid]
  4001                              <1>         	; cmpb u.uid,i.uid / is user same as owner
  4002 0000405F 7413                <1> 	je	short mdate_1
  4003                              <1>         	; beq 1f / yes
  4004 00004061 20C0                <1> 	and	al, al
  4005                              <1> 		; tstb u.uid / no, is user the super user
  4006                              <1> 	;jnz	error
  4007                              <1> 		; bne error2 / no, error
  4008 00004063 740F                <1> 	jz	short mdate_1
  4009 00004065 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  4009 0000406D 0000                <1>
  4010                              <1> sysstty_err:	; 04/02/2022
  4011 0000406F E95EFAFFFF          <1> 	jmp	error
  4012                              <1> mdate_1: ;1:
  4013 00004074 E82B120000          <1> 	call	setimod
  4014                              <1>         	; jsr r0,setimod / fill in modification data,
  4015                              <1> 		               ; / time etc.
  4016 00004079 BE[206B0000]        <1> 	mov	esi, p_time
  4017 0000407E BF[B26B0000]        <1> 	mov	edi, i.mtim
  4018 00004083 A5                  <1> 	movsd
  4019                              <1> 		; mov 4(sp),i.mtim / move present time to
  4020                              <1>         	; mov 2(sp),i.mtim+2 / modification time
  4021 00004084 E969FAFFFF          <1>         jmp	sysret
  4022                              <1> 		; br sysret2
  4023                              <1> 
  4024                              <1> 	; 04/02/2022
  4025                              <1> sysstty_err_s:
  4026 00004089 880D[986E0000]      <1> 	mov	byte [u.r0], cl ; serial port's tty number
  4027 0000408F EBDE                <1> 	jmp	short sysstty_err
  4028                              <1> 
  4029                              <1> sysstty: ; < set tty status and mode >
  4030                              <1> 	; 26/02/2022
  4031                              <1> 	; 04/02/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4032                              <1> 	; 02/02/2022 (Retro UNIX 386 v1, Kernel v0.2.0.18)
  4033                              <1> 	; 01/02/2022 (Retro UNIX 386 v1) -clear screen-
  4034                              <1> 	; 17/11/2015
  4035                              <1> 	; 12/11/2015
  4036                              <1> 	; 29/10/2015
  4037                              <1> 	; 17/10/2015
  4038                              <1> 	; 13/10/2015
  4039                              <1> 	; 29/06/2015
  4040                              <1> 	; 27/06/2015 (Retro UNIX 386 v1 - Beginning)
  4041                              <1> 	; 02/06/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4042                              <1> 	;
  4043                              <1> 	; 'sysstty' sets the status and mode of the typewriter 
  4044                              <1> 	; whose file descriptor is in (u.r0).
  4045                              <1> 	;
  4046                              <1> 	; Calling sequence:
  4047                              <1> 	;	sysstty; arg
  4048                              <1> 	; Arguments:
  4049                              <1> 	;	arg - address of 3 consequitive words that contain
  4050                              <1> 	;	      the source of status data	
  4051                              <1> 	; Inputs: ((*u.r0 - file descriptor & argument))
  4052                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4053                              <1> 	; ...............................................................
  4054                              <1> 	;	
  4055                              <1> 	; Retro UNIX 8086 v1 modification: 
  4056                              <1> 	;	'sysstty' system call will set the tty
  4057                              <1> 	;	(clear keyboard buffer and set cursor position)
  4058                              <1> 	;	 in following manner:
  4059                              <1> 	;   NOTE: All of tty setting functions are here (16/01/2014)
  4060                              <1> 	;
  4061                              <1> 	; Inputs:
  4062                              <1> 	;	BX = 0 --> means
  4063                              <1> 	;	   If CL = FFh (& DX <> 0FFFFh) ; 01/02/2022
  4064                              <1> 	;	      set cursor position for console tty, only 
  4065                              <1> 	;	      CH will be ignored (char. will not be written)	
  4066                              <1> 	;	   If CH = 0 (& DX <> 0FFFFh & CL < FFh) ; 01/02/20222
  4067                              <1> 	;	      set console tty for (current) process
  4068                              <1> 	;	      CL = tty number (0 to 9)
  4069                              <1> 	;	      (If CH = 0, character will not be written)			
  4070                              <1> 	;          If CH > 0 (CL < FFh)	
  4071                              <1> 	;             CL = tty number (0 to 9)
  4072                              <1> 	;	      CH = character will be written
  4073                              <1> 	;	        at requested cursor position (in DX)	
  4074                              <1> 	;	   DX = cursor position for tty number 0 to 7.	
  4075                              <1>   	;		(only tty number 0 to 7) 
  4076                              <1> 	;          DL = communication parameters (for serial ports) 
  4077                              <1> 	;	        (only for COM1 and COM2 serial ports)
  4078                              <1> 	;	   DH < 0FFh -> DL is valid, initialize serial port
  4079                              <1> 	;			or set cursor position	
  4080                              <1> 	;	   DH = 0FFh -> DL is not valid
  4081                              <1> 	;		do not set serial port parameters 
  4082                              <1> 	;		or do not set cursor position
  4083                              <1> 	;
  4084                              <1> 	;	BX > 0 --> points to name of tty
  4085                              <1> 	;    	   CH > 0 -->
  4086                              <1> 	;		CH = character will be written in current 
  4087                              <1> 	;            	cursor position (for tty number from 0 to 7)
  4088                              <1> 	;	     	or character will be sent to serial port
  4089                              <1> 	;	     	(for tty number 8 or 9)
  4090                              <1> 	;		CL = color of the character if tty number < 8.
  4091                              <1> 	;    	   CH = 0 --> Do not write a character, 
  4092                              <1> 	;		set mode (tty 8 to 9) or 
  4093                              <1> 	;		set current cursor positions (tty 0 to 7) only.
  4094                              <1> 	;   	   DX = cursor position for tty number 0 to 7.
  4095                              <1> 	;    	   DH = FFh --> Do not set cursor pos (or comm. params.)
  4096                              <1> 	;		(DL is not valid)
  4097                              <1> 	;	   DL = communication parameters 
  4098                              <1> 	;		for tty number 8 or 9 (COM1 or COM2).
  4099                              <1> 	;
  4100                              <1> 	;	01/02/2022 - Retro UNIX 386 v1 - 2022 modification
  4101                              <1> 	;	(30/01/2022 - Retro UNIX 8086 - 2022 modification)
  4102                              <1> 	;	If CH = 0 & DX = 0FFFFh -> 
  4103                              <1> 	;	   clear screen (video page) & set cursor pos to 0,0.
  4104                              <1> 	;	   (for tty number 0 to 7, CL <= 7)
  4105                              <1> 	;	   (if CL = 0FFh -> clear console tty)	
  4106                              <1> 	;
  4107                              <1> 	; Outputs:
  4108                              <1> 	;	cf = 0 -> OK
  4109                              <1> 	;	     AL = tty number (0 to 9)
  4110                              <1> 	;	     AH = line status if tty number is 8 or 9
  4111                              <1> 	;	     AH = process number (of the caller) 	
  4112                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4113                              <1> 	;	     AH = FFh if the tty is locked 
  4114                              <1> 	;		  (owned by another process)
  4115                              <1> 	;	        = process number (of the caller) 
  4116                              <1> 	;		  (if < FFh and tty number < 8)
  4117                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4118                              <1> 	;	     AH = line status if tty number is 8 or 9
  4119                              <1> 	;	NOTE: Video page will be cleared if cf = 0.
  4120                              <1> 	;	
  4121                              <1> 
  4122                              <1> 	; 27/06/2015 (32 bit modifications)
  4123                              <1> 	; 14/01/2014
  4124 00004091 31C0                <1> 	xor 	eax, eax
  4125 00004093 6648                <1> 	dec	ax ; 17/10/2015
  4126 00004095 A3[986E0000]        <1> 	mov	[u.r0], eax ; 0FFFFh
  4127                              <1> 	;;;
  4128                              <1> 	; 01/02/2022
  4129 0000409A FEC1                <1> 	inc	cl  ; 0FFh -> 0, 7 -> 8
  4130 0000409C 39C2                <1> 	cmp	edx, eax
  4131                              <1> 	;cmp	dx, ax ; 0FFFFh
  4132 0000409E 7521                <1> 	jne	short sysstty_18
  4133                              <1> 	; clear video page
  4134                              <1> 	; (CH must be 0)
  4135 000040A0 08ED                <1> 	or	ch, ch
  4136 000040A2 75CB                <1> 	jnz	short sysstty_err ; invalid parameters
  4137 000040A4 80F908              <1> 	cmp	cl, 8 ; > tty7 (serial port?)
  4138 000040A7 77C6                <1> 	ja	short sysstty_err ; invalid parameters
  4139 000040A9 20C9                <1> 	and	cl, cl
  4140 000040AB 7514                <1> 	jnz	short sysstty_18 ; actual tty (video page) num + 1
  4141 000040AD 0FB635[E76E0000]    <1> 	movzx	esi, byte [u.uno]
  4142 000040B4 8A8E[F76B0000]      <1> 	mov	cl, byte [esi+p.ttyc-1] ; current/console tty
  4143 000040BA 80F907              <1> 	cmp	cl, 7
  4144 000040BD 77CA                <1> 	ja	short sysstty_err_s ; serial port !	 
  4145                              <1> 	; here CL contains (actual) tty number (tty0 to tty7) 
  4146 000040BF FEC1                <1> 	inc	cl  ; 0 -> 1, 7 -> 8 
  4147                              <1> sysstty_18:
  4148 000040C1 FEC9                <1> 	dec	cl  ; 8 -> 7, 1 -> 0
  4149                              <1> 	; cl = video page (tty) number		
  4150                              <1> 	;;;
  4151 000040C3 21DB                <1> 	and	ebx, ebx
  4152                              <1> 	;jnz	sysstty_6
  4153                              <1> 	; 01/02/2022
  4154 000040C5 7405                <1> 	jz	short sysstty_19
  4155 000040C7 E9C2000000          <1> 	jmp	sysstty_6
  4156                              <1> sysstty_19:
  4157                              <1> 	; set console tty
  4158                              <1> 	; 29/10/2015
  4159                              <1> 	; 17/01/2014 
  4160 000040CC 80F909              <1> 	cmp	cl, 9
  4161 000040CF 7613                <1> 	jna	short sysstty_0
  4162                              <1> 	; 17/11/2015
  4163 000040D1 80F9FF              <1> 	cmp	cl, 0FFh
  4164 000040D4 7202                <1> 	jb	short sysstty_13
  4165 000040D6 88CD                <1> 	mov	ch, cl ; force CH value to FFh 
  4166                              <1> sysstty_13:
  4167 000040D8 8A1D[E76E0000]      <1> 	mov	bl, [u.uno] ; process number
  4168 000040DE 8A8B[F76B0000]      <1> 	mov	cl, [ebx+p.ttyc-1] ; current/console tty
  4169                              <1> sysstty_0:
  4170                              <1> 	; 29/06/2015
  4171                              <1> 	;push	dx
  4172                              <1> 	;push	cx
  4173                              <1> 	; 01/02/2022
  4174 000040E4 52                  <1> 	push	edx
  4175 000040E5 51                  <1> 	push	ecx
  4176 000040E6 30D2                <1> 	xor 	dl, dl	; sysstty call sign
  4177 000040E8 88C8                <1> 	mov	al, cl
  4178 000040EA A2[986E0000]        <1> 	mov	[u.r0], al ; tty number (0 to 9)
  4179 000040EF E8C4180000          <1> 	call	ottyp
  4180                              <1> 	; 01/02/2022
  4181 000040F4 59                  <1> 	pop	ecx
  4182 000040F5 5A                  <1> 	pop	edx
  4183                              <1> 	;pop	cx
  4184                              <1> 	;pop	dx
  4185                              <1> 	;
  4186 000040F6 7220                <1> 	jc	short sysstty_pd_err
  4187                              <1> 	;
  4188                              <1> 	; 26/02/2022 (Bug! BugFix)
  4189                              <1> 	; (ebx = ?, modified in ottyp, it may be > 255)
  4190                              <1> 	;
  4191 000040F8 80F908              <1> 	cmp	cl, 8
  4192 000040FB 720C                <1> 	jb	short sysstty_2
  4193                              <1> 	;
  4194 000040FD 80FEFF              <1> 	cmp	dh, 0FFh
  4195 00004100 7407                <1> 	je	short sysstty_2
  4196                              <1> 		; set communication parameters for serial ports
  4197                              <1> 
  4198                              <1> ; 01/02/2022
  4199                              <1> ;	; 29/10/2015
  4200                              <1> ;	mov	ah, dl ; communication parameters
  4201                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4202                              <1> ;		;			 THRE int + RDA int 
  4203                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4204                              <1> ;		;			 THRE int + RDA int 
  4205                              <1> ;	sub	al, al ; 0
  4206                              <1> ;	; 12/07/2014
  4207                              <1> ;	cmp	cl, 9
  4208                              <1> ;	jb	short sysstty_1
  4209                              <1> ;	inc	al
  4210                              <1> ;sysstty_1:
  4211                              <1> ;	; 01/02/2022
  4212                              <1> ;	push	ecx
  4213                              <1> ;	;push	cx
  4214                              <1> ;	; 29/06/2015	
  4215                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4216                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4217                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4218                              <1> ;	; 01/02/2022
  4219                              <1> ;	pop	ecx	
  4220                              <1> ;	;pop	cx
  4221                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4222                              <1> 
  4223                              <1> 	; 01/02/2022
  4224 00004102 E830010000          <1> 	call	sysstty_scp
  4225 00004107 7276                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4226                              <1> 
  4227                              <1> sysstty_2:
  4228                              <1> 	; 17/01/2014
  4229 00004109 20ED                <1> 	and	ch, ch 	; set cursor position 
  4230                              <1> 			; or comm. parameters ONLY
  4231 0000410B 7527                <1> 	jnz	short sysstty_3
  4232                              <1> 	; 01/02/2022
  4233 0000410D 6683FAFF            <1> 	cmp	dx, 0FFFFh
  4234 00004111 7214                <1> 	jb	short sysstty_20
  4235                              <1> 	; clear screen (video page)
  4236 00004113 E93B010000          <1> 	jmp	sysstty_14
  4237                              <1> 
  4238                              <1> sysstty_pd_err: ; 29/06/2015
  4239                              <1> 	; 'permission denied !' error
  4240 00004118 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER
  4240 00004120 0000                <1>
  4241 00004122 E9ABF9FFFF          <1> 	jmp	error
  4242                              <1> 
  4243                              <1> sysstty_20:
  4244 00004127 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4245 0000412E 888B[F76B0000]      <1> 	mov	[ebx+p.ttyc-1], cl ; console tty
  4246                              <1> sysstty_3:
  4247                              <1> 	; 16/01/2014
  4248 00004134 88E8                <1> 	mov	al, ch ; character ; 0 to FFh
  4249                              <1> 	; 17/11/2015
  4250 00004136 B507                <1> 	mov 	ch, 7  ; Default color (light gray)
  4251 00004138 38E9                <1> 	cmp	cl, ch ; 7 (tty number)
  4252                              <1> 	;jna	sysstty_9
  4253                              <1> 	; 01/02/2022
  4254 0000413A 7705                <1> 	ja	short sysstty_12
  4255 0000413C E9C5000000          <1> 	jmp	sysstty_9
  4256                              <1> 
  4257                              <1> sysstty_12:
  4258                              <1> 	;; BX = 0, CL = 8 or CL = 9
  4259                              <1> 	; (Set specified serial port as console tty port)
  4260                              <1> 	; CH = character to be written
  4261                              <1> 	; 15/04/2014
  4262                              <1> 	; CH = 0 --> initialization only
  4263                              <1> 	; AL = character
  4264                              <1> 	; 26/06/2014
  4265 00004141 880D[EC6E0000]      <1> 	mov	[u.ttyn], cl
  4266                              <1> 	; 12/07/2014
  4267 00004147 88CC                <1> 	mov	ah, cl ; tty number (8 or 9)
  4268                              <1> 	; 02/02/2022
  4269 00004149 FEC0                <1> 	inc	al  ; 0FFh -> 0, 0 -> 1
  4270 0000414B 740B                <1> 	jz	short sysstty_4 ; al = ch = 0	
  4271 0000414D FEC8                <1> 	dec	al  ; 1 -> 0	
  4272                              <1> 	;and	al, al
  4273 0000414F 7407                <1> 	jz	short sysstty_4 ; al = ch = 0
  4274                              <1>  	; 04/07/2014
  4275 00004151 E89E1E0000          <1> 	call 	sndc
  4276                              <1> 	; 12/07/2014
  4277 00004156 EB0C                <1> 	jmp	short sysstty_5
  4278                              <1> 
  4279                              <1> sysstty_4:
  4280                              <1> 	; 12/07/2014
  4281                              <1> 	;xchg 	ah, al ; al = 0 -> al = ah, ah = 0
  4282 00004158 88E0                <1> 	mov	al, ah ; 29/06/2015
  4283 0000415A 2C08                <1> 	sub	al, 8
  4284                              <1> 	; 27/06/2015
  4285 0000415C E819F4FFFF          <1> 	call	sp_status ; get serial port status
  4286                              <1> 	; AL = Line status, AH = Modem status
  4287                              <1> 	; 12/11/2015
  4288 00004161 3C80                <1> 	cmp	al, 80h
  4289 00004163 F5                  <1> 	cmc
  4290                              <1> sysstty_5:
  4291 00004164 66A3[996E0000]      <1> 	mov	[u.r0+1], ax ; ah = line status
  4292                              <1> 		; EAX bits 16-23 = modem status	
  4293 0000416A 9C                  <1> 	pushf
  4294 0000416B 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4295 0000416D A0[EC6E0000]        <1> 	mov	al, [u.ttyn] ; 26/06/2014
  4296 00004172 E864190000          <1> 	call	cttyp
  4297 00004177 9D                  <1> 	popf
  4298                              <1> 	;jnc	sysret ; time out error 
  4299                              <1> 	; 01/02/2022
  4300 00004178 7205                <1> 	jc	short sysstty_tmout_err
  4301 0000417A E973F9FFFF          <1> 	jmp	sysret
  4302                              <1> 
  4303                              <1> sysstty_tmout_err:
  4304 0000417F C705[ED6E0000]1900- <1> 	mov	dword [u.error], ERR_TIME_OUT
  4304 00004187 0000                <1>
  4305 00004189 E944F9FFFF          <1> 	jmp	error
  4306                              <1> 
  4307                              <1> sysstty_6:
  4308                              <1> 	;push	dx
  4309                              <1> 	;push	cx
  4310                              <1> 	; 01/02/2022
  4311 0000418E 52                  <1> 	push	edx
  4312 0000418F 51                  <1> 	push	ecx
  4313 00004190 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  4314 00004196 E835080000          <1> 	call	namei
  4315                              <1> 	; 01/02/2022
  4316 0000419B 59                  <1> 	pop	ecx
  4317 0000419C 5A                  <1> 	pop	edx
  4318                              <1> 	;pop	cx
  4319                              <1> 	;pop	dx
  4320 0000419D 7258                <1> 	jc	short sysstty_inv_dn
  4321                              <1> 	;
  4322 0000419F 6683F813            <1> 	cmp	ax, 19  ; inode number of /dev/COM2
  4323 000041A3 7752                <1> 	ja	short sysstty_inv_dn ; 27/06/2015
  4324                              <1> 	;
  4325 000041A5 3C0A                <1> 	cmp	al, 10 ; /dev/tty0 .. /dev/tty7
  4326                              <1> 		       ; /dev/COM1, /dev/COM2
  4327 000041A7 7204                <1> 	jb	short sysstty_7
  4328 000041A9 2C0A                <1> 	sub	al, 10
  4329 000041AB EB11                <1> 	jmp	short sysstty_8
  4330                              <1> 
  4331                              <1> sysstty_7:
  4332 000041AD 3C01                <1> 	cmp	al, 1 ; /dev/tty
  4333 000041AF 7546                <1> 	jne	short sysstty_inv_dn ; 27/06/2015
  4334 000041B1 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  4335 000041B8 8A83[F76B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; console tty
  4336                              <1> sysstty_8:
  4337                              <1> 	; 26/02/2022
  4338                              <1> 	; (ebx < 256)	
  4339 000041BE A2[986E0000]        <1> 	mov	[u.r0], al
  4340                              <1> 	; 01/02/2022
  4341                              <1> 	;push	dx
  4342                              <1> 	;push	ax
  4343                              <1> 	;push	cx
  4344 000041C3 52                  <1> 	push	edx
  4345 000041C4 50                  <1> 	push	eax
  4346 000041C5 51                  <1> 	push	ecx	
  4347 000041C6 E8ED170000          <1> 	call	ottyp
  4348 000041CB 59                  <1> 	pop	ecx
  4349 000041CC 58                  <1> 	pop	eax
  4350 000041CD 5A                  <1> 	pop	edx
  4351                              <1> 	;pop	cx
  4352                              <1> 	;pop	ax
  4353                              <1> 	;pop	dx
  4354                              <1>         ;jc	sysstty_pd_err ; 'permission denied !'
  4355                              <1> 	; 01/02/2022
  4356 000041CE 7305                <1> 	jnc	short sysstty_21
  4357 000041D0 E943FFFFFF          <1> 	jmp	sysstty_pd_err ; 'permission denied !'
  4358                              <1> sysstty_21:
  4359                              <1> 	; 29/10/2015
  4360 000041D5 86E9                <1> 	xchg 	ch, cl
  4361                              <1> 		; cl = character, ch = color code
  4362 000041D7 86C1                <1> 	xchg	al, cl
  4363                              <1> 		; al = character, cl = tty number
  4364 000041D9 80F907              <1> 	cmp	cl, 7
  4365                              <1> 	;ja	sysstty_12
  4366                              <1> 	; 01/02/2022
  4367 000041DC 7628                <1> 	jna	short sysstty_16
  4368                              <1> ;;
  4369 000041DE 80FEFF              <1> 	cmp	dh, 0FFh
  4370 000041E1 740B                <1> 	je	short sysstty_22 ; do not set comm. parameters
  4371                              <1> 
  4372                              <1> ; 01/02/2022
  4373                              <1> ;	; 29/10/2015
  4374                              <1> ;	mov	ah, dl ; communication parameters
  4375                              <1> ;		; ah = 0E3h = 11100011b = 115200 baud,
  4376                              <1> ;		;			 THRE int + RDA int 
  4377                              <1> ;		; ah = 23h = 00100011b = 9600 baud,
  4378                              <1> ;		;			 THRE int + RDA int 
  4379                              <1> ;	sub	al, al ; 0
  4380                              <1> ;	; 12/07/2014
  4381                              <1> ;	cmp	cl, 9
  4382                              <1> ;	jb	short sysstty_1
  4383                              <1> ;	inc	al
  4384                              <1> ;sysstty_1:
  4385                              <1> ;	; 01/02/2022
  4386                              <1> ;	push	ecx
  4387                              <1> ;	;push	cx
  4388                              <1> ;	; 29/06/2015	
  4389                              <1> ;	call 	sp_setp ; Set serial port communication parameters
  4390                              <1> ;	mov	[u.r0+1], cx ; Line status (ah)
  4391                              <1> ;			     ; Modem status (EAX bits 16 to 23)
  4392                              <1> ;	; 01/02/2022
  4393                              <1> ;	pop	ecx	
  4394                              <1> ;	;pop	cx
  4395                              <1> ;       jc      short sysstty_tmout_err ; 29/10/2015
  4396                              <1> 
  4397                              <1> 	; 02/02/2022
  4398 000041E3 88C5                <1> 	mov	ch, al ; save char
  4399                              <1> 	; 01/02/2022
  4400 000041E5 E84D000000          <1> 	call	sysstty_scp
  4401 000041EA 7293                <1>         jc      short sysstty_tmout_err ; 29/10/2015
  4402                              <1> 	; 02/02/2022
  4403 000041EC 88E8                <1> 	mov	al, ch ; restore char
  4404                              <1> sysstty_22:
  4405                              <1> 	; 01/02/2022
  4406 000041EE 08ED                <1> 	or	ch, ch
  4407 000041F0 7437                <1> 	jz	short sysstty_11 ; do not send char to terminal
  4408                              <1> 	; send char to (serial port) terminal
  4409                              <1> 	; al = character
  4410                              <1> 	; cl = tty number (8 or 9)
  4411 000041F2 E94AFFFFFF          <1> 	jmp	sysstty_12 ; (tty8 or tty9)
  4412                              <1> 
  4413                              <1> sysstty_inv_dn: 
  4414                              <1> 	; 27/06/2015
  4415                              <1> 	; Invalid device name (not a tty) ! error
  4416                              <1> 	; (Device is not a tty or device name not found)
  4417 000041F7 C705[ED6E0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4417 000041FF 0000                <1>
  4418 00004201 E9CCF8FFFF          <1> 	jmp	error 
  4419                              <1> 
  4420                              <1> sysstty_16:
  4421                              <1> 	; 26/02/2022
  4422                              <1> 	; 16/01/2014
  4423                              <1> 	;xor	bh, bh
  4424                              <1> 	; 02/02/2022
  4425                              <1> sysstty_9: 	; tty 0 to tty 7
  4426                              <1> 	; al = character
  4427                              <1> 	; ch = color/attribute ; 01/02/2022
  4428                              <1> 	;
  4429                              <1> 	; 26/02/2022 (BugFix)
  4430                              <1> 	; (ebx may be > 255 here!? due to 'ottyp')
  4431 00004206 29DB                <1> 	sub	ebx, ebx ; *
  4432 00004208 80FEFF              <1> 	cmp	dh, 0FFh ; Do not set cursor position
  4433 0000420B 740B                <1> 	je	short sysstty_10
  4434                              <1> 	; 02/02/2022
  4435 0000420D 51                  <1> 	push	ecx
  4436 0000420E 50                  <1> 	push	eax
  4437                              <1> 	;push	cx
  4438                              <1> 	;push	ax	
  4439                              <1> 	;movzx	ebx, cl
  4440 0000420F 88CB                <1> 	mov	bl, cl ; (tty number = video page number)
  4441 00004211 E8BAD2FFFF          <1> 	call	set_cpos
  4442                              <1> 	;pop	ax
  4443                              <1> 	;pop	cx
  4444                              <1> 	; 02/02/2022
  4445 00004216 58                  <1> 	pop	eax
  4446 00004217 59                  <1> 	pop	ecx
  4447                              <1> sysstty_10: 
  4448                              <1> 	; 29/10/2015
  4449 00004218 08C0                <1> 	or	al, al ; character
  4450 0000421A 740D                <1> 	jz      short sysstty_11 ; al = 0
  4451                              <1> 	; 17/11/2015
  4452 0000421C 3CFF                <1> 	cmp	al, 0FFh
  4453 0000421E 7309                <1> 	jnb	short sysstty_11
  4454                              <1> 		; ch > 0 and ch < FFh
  4455                              <1> 	; write a character at current cursor position
  4456 00004220 88EC                <1> 	mov	ah, ch ; color/attribute
  4457                              <1> 	; 12/07/2014
  4458                              <1> 	;push	cx
  4459                              <1> 	; 02/02/2022
  4460 00004222 51                  <1> 	push	ecx
  4461 00004223 E894D3FFFF          <1> 	call	write_c_current
  4462                              <1> 	;pop	cx
  4463                              <1> 	; 02/02/2022
  4464 00004228 59                  <1> 	pop	ecx
  4465                              <1> sysstty_11:
  4466                              <1> 	; 14/01/2014
  4467 00004229 30D2                <1> 	xor	dl, dl ; sysstty call sign
  4468                              <1> 	; 18/01/2014
  4469                              <1> 	;movzx	eax, cl ; 27/06/2015
  4470 0000422B 88C8                <1> 	mov	al, cl
  4471 0000422D E8A9180000          <1> 	call	cttyp
  4472 00004232 E9BBF8FFFF          <1> 	jmp	sysret
  4473                              <1> 
  4474                              <1> sysstty_scp:
  4475                              <1> 	; 02/02/2022
  4476                              <1> 	; set communication parameters (for COM1 or COM2)
  4477                              <1> 	; 01/02/2022
  4478                              <1> 	;
  4479                              <1> 	; 29/10/2015
  4480 00004237 88D4                <1> 	mov	ah, dl ; communication parameters
  4481                              <1> 		; ah = 0E3h = 11100011b = 115200 baud,
  4482                              <1> 		;			 THRE int + RDA int 
  4483                              <1> 		; ah = 23h = 00100011b = 9600 baud,
  4484                              <1> 		;			 THRE int + RDA int 
  4485 00004239 28C0                <1> 	sub	al, al ; 0
  4486                              <1> 	; 12/07/2014
  4487 0000423B 80F909              <1> 	cmp	cl, 9
  4488 0000423E 7202                <1> 	jb	short sysstty_1
  4489 00004240 FEC0                <1> 	inc	al
  4490                              <1> sysstty_1:
  4491                              <1> 	; 02/02/2022
  4492 00004242 52                  <1> 	push	edx
  4493                              <1> 	; 01/02/2022
  4494 00004243 51                  <1> 	push	ecx
  4495                              <1> 	;push	cx
  4496                              <1> 	; 29/06/2015	
  4497 00004244 E839F3FFFF          <1> 	call 	sp_setp ; Set serial port communication parameters
  4498 00004249 66890D[996E0000]    <1> 	mov	[u.r0+1], cx ; Line status (ah)
  4499                              <1> 			     ; Modem status (EAX bits 16 to 23)
  4500                              <1> 	; 01/02/2022
  4501 00004250 59                  <1> 	pop	ecx	
  4502                              <1> 	;pop	cx
  4503 00004251 5A                  <1> 	pop	edx ; 02/02/2022
  4504                              <1> 	; 01/02/2022
  4505                              <1> 	; if cf = 1 -> sysstty_tmout_err
  4506 00004252 C3                  <1> 	retn
  4507                              <1> 
  4508                              <1> sysstty_14:
  4509                              <1> 	; 26/02/2022
  4510                              <1> 	; 02/02/2022
  4511                              <1> 	; ch = 0
  4512                              <1> 	; cl = video page
  4513                              <1> 	;
  4514                              <1> 	; dx = 0FFFFh
  4515                              <1> 	; clear screen (video page)
  4516                              <1> 	;
  4517                              <1> 
  4518                              <1> 	; 02/02/2022
  4519                              <1> 	; clear screen
  4520                              <1> 	;
  4521                              <1> 	; (modified registers: eax, ebx, ecx, edx, esi, edi)
  4522                              <1> 	; clear video page
  4523                              <1> 
  4524                              <1> 	; 26/02/2022
  4525 00004253 88CB                <1> 	mov 	bl, cl ; CL = tty number (0 to 7)
  4526                              <1> 
  4527                              <1> 	; clear video page
  4528 00004255 E810000000          <1> 	call	wttyc ; 26/02/2022
  4529                              <1> 
  4530                              <1> 	; 26/02/2022
  4531 0000425A 88D8                <1> 	mov	al, bl
  4532 0000425C 8A25[E76E0000]      <1> 	mov	ah, [u.uno]
  4533 00004262 66A3[986E0000]      <1> 	mov	[u.r0], ax
  4534 00004268 EBBF                <1> 	jmp	short sysstty_11
  4535                              <1> 
  4536                              <1> vp_clr:	; 27/02/2022
  4537                              <1> wttyc:
  4538                              <1> 	; 23/02/2022
  4539                              <1> 	; (clear video page)
  4540                              <1> 	; INPUT:
  4541                              <1> 	;  bl = video page (0 to 7)
  4542                              <1> 	;
  4543                              <1> 	; Modified registers: eax, ecx, edx, esi, edi
  4544                              <1> 
  4545                              <1> 	;xor	dx, dx ; column 0, row 0
  4546                              <1> 	;;inc	dx ; 0 ; 23/02/2022
  4547                              <1> 	;
  4548                              <1> ;	movzx	ebx, cl
  4549                              <1> ;	mov 	bl, cl ; CL = tty number (0 to 7) ; 23/02/2022
  4550                              <1> 
  4551                              <1> ;	shl 	bl, 1 
  4552                              <1> ;	mov 	al, byte ptr [ebx+ttyl]
  4553                              <1> ;		; AL = lock value (0 or process number)
  4554                              <1> ;	or	al, al
  4555                              <1> ;	jz	short @f
  4556                              <1> ;	cmp	al, byte ptr [u.uno] ; process number
  4557                              <1> ;	jne	short sysstty_15
  4558                              <1> ;		; only the owner can clear its video page
  4559                              <1> ;	xor	al, al ; 0
  4560                              <1> ;@@:
  4561                              <1> ;	;mov	bl, cl		
  4562                              <1> ;	shr	bl, 1 
  4563                              <1> 
  4564 0000426A 30C0                <1> 	xor	al, al	; 0
  4565 0000426C B407                <1> 	mov 	ah, 07h	; attribute/color (default)
  4566                              <1> 
  4567                              <1> 	; scroll_up input:
  4568                              <1> 	;
  4569                              <1> 	; al = line count (0 or 1) ((0 == clear video page))
  4570                              <1> 	; 	((al = 1 for write_tty (putc) procedure))
  4571                              <1> 	; ah = attribute to be used on blanked line
  4572                              <1> 	; bl = video page number (0 to 7)
  4573                              <1> 
  4574 0000426E E8E7D2FFFF          <1> 	call	scroll_up ; clear video page (al=0)
  4575                              <1> 
  4576                              <1> 	; (modified registers: eax, ecx, edx, esi, edi)
  4577                              <1> 
  4578                              <1> 	; bl = video page number (0 to 7)
  4579                              <1> 	;xor	dx, dx ; column 0, row 0
  4580                              <1> 	; 02/02/2022
  4581 00004273 31D2                <1> 	xor	edx, edx
  4582                              <1> 	; 26/02/2022
  4583                              <1> 	;call	set_cpos
  4584                              <1> 	;retn
  4585 00004275 E956D2FFFF          <1> 	jmp	set_cpos
  4586                              <1> 
  4587                              <1> 	;mov	al, bl
  4588                              <1> 	;mov	ah, [u.uno]
  4589                              <1> 	;mov	[u.r0], ax
  4590                              <1> 	;jmp	short sysstty_11
  4591                              <1> 
  4592                              <1> ;sysstty_15:
  4593                              <1> ;	; 30/01/2022
  4594                              <1> ;	; permission (denied) error
  4595                              <1> ;	;xor	dl, dl ; sysstty call sign
  4596                              <1> ;	mov	al, cl
  4597                              <1> ;	sub	ah, ah ; 0
  4598                              <1> ;	call	cttyp
  4599                              <1> ;	jmp	error
  4600                              <1> 
  4601                              <1> ; Original UNIX v1 'sysstty' routine:
  4602                              <1> ; gtty:
  4603                              <1> ;sysstty: / set mode of typewriter; 3 consequtive word arguments
  4604                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block, 
  4605                              <1> 	; 		/ r2 has source
  4606                              <1>         ;mov    r2,-(sp)
  4607                              <1>         ;mov    r1,-(sp) / put r1 and r2 on the stack
  4608                              <1> ;1: / flush the clist wait till typewriter is quiescent
  4609                              <1>         ;mov    (sp),r1 / restore r1 to tty block offset
  4610                              <1>         ;movb   tty+3(r1),0f / put cc offset into getc argument
  4611                              <1>         ;mov    $240,*$ps / set processor priority to 5
  4612                              <1>         ;jsr    r0,getc; 0:../ put character from clist in r1
  4613                              <1>         ;       br .+4 / list empty, skip branch
  4614                              <1>         ;br     1b / get another character until list is empty
  4615                              <1>         ;mov    0b,r1 / move cc offset to r1
  4616                              <1>         ;inc    r1 / bump it for output clist
  4617                              <1>         ;tstb   cc(r1) / is it 0
  4618                              <1>         ;beq    1f / yes, no characters to output
  4619                              <1>  	;mov    r1,0f / no, put offset in sleep arg
  4620                              <1>         ;jsr    r0,sleep; 0:.. / put tty output process to sleep
  4621                              <1>         ;br     1b / try to calm it down again
  4622                              <1> ;1:
  4623                              <1>         ;mov    (sp)+,r1
  4624                              <1>         ;mov    (sp)+,r2 / restore registers
  4625                              <1> 	;mov    (r2)+,r3 / put reader control status in r3
  4626                              <1>         ;beq    1f / if 0, 1f
  4627                              <1>         ;mov    r3,rcsr(r1) / move r.c. status to reader
  4628                              <1>         ;                   / control status register
  4629                              <1> ;1:
  4630                              <1>         ;mov    (r2)+,r3 / move pointer control status to r3
  4631                              <1>         ;beq    1f / if 0 1f
  4632                              <1>         ;mov    r3,tcsr(r1) / move p.c. status to printer 
  4633                              <1> 	;		    / control status reg
  4634                              <1> ;1:
  4635                              <1>         ;mov    (r2)+,tty+4(r1) / move to flag byte of tty block
  4636                              <1>         ;jmp     sysret2 / return to user
  4637                              <1> 
  4638                              <1> sysgtty: ; < get tty status >
  4639                              <1> 	; 26/02/2022
  4640                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4641                              <1> 	;	    ((32 bit reg push/pop))
  4642                              <1> 	; 23/11/2015
  4643                              <1> 	; 29/10/2015
  4644                              <1> 	; 17/10/2015
  4645                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - Beginning)
  4646                              <1> 	; 30/05/2013 - 12/07/2014 (Retro UNIX 8086 v1)
  4647                              <1> 	;
  4648                              <1> 	; 'sysgtty' gets the status of tty in question. 
  4649                              <1> 	; It stores in the three words addressed by it's argument
  4650                              <1> 	; the status of the typewriter whose file descriptor
  4651                              <1> 	; in (u.r0).
  4652                              <1> 	;
  4653                              <1> 	; Calling sequence:
  4654                              <1> 	;	sysgtty; arg
  4655                              <1> 	; Arguments:
  4656                              <1> 	;	arg - address of 3 words destination of the status
  4657                              <1> 	; Inputs: ((*u.r0 - file descriptor))
  4658                              <1> 	; Outputs: ((status in address which is pointed to by arg))
  4659                              <1> 	; ...............................................................
  4660                              <1> 	;	
  4661                              <1> 	; Retro UNIX 8086 v1 modification: 
  4662                              <1> 	;	'sysgtty' system call will return status of tty
  4663                              <1> 	;	(keyboard, serial port and video page status)
  4664                              <1> 	;	 in following manner:
  4665                              <1> 	;
  4666                              <1> 	; Inputs:
  4667                              <1> 	;	BX = 0 --> means 
  4668                              <1> 	;	     CH = 0 -->	'return status of the console tty' 
  4669                              <1> 	;	                 for (current) process
  4670                              <1> 	;	     CL = 0 --> return keyboard status (tty 0 to 9)
  4671                              <1> 	;	     CL = 1 --> return video page status (tty 0 to 7)
  4672                              <1> 	;	     CL = 1 --> return serial port status (tty 8 & 9)		
  4673                              <1> 	;	     CH > 0 -->	tty number + 1
  4674                              <1> 	;
  4675                              <1> 	;	BX > 0 --> points to name of tty
  4676                              <1> 	;	     CL = 0 --> return keyboard status
  4677                              <1> 	;	     CL = 1 --> return video page status
  4678                              <1> 	;	     CH = undefined		 
  4679                              <1> 	;
  4680                              <1> 	; Outputs:
  4681                              <1> 	;	cf = 0 ->
  4682                              <1> 	;
  4683                              <1> 	;	     AL = tty number from 0 to 9
  4684                              <1> 	;		  (0 to 7 is also the video page of the tty)	
  4685                              <1> 	;	     AH = 0 if the tty is free/unused
  4686                              <1> 	;	     AH = the process number of the caller 
  4687                              <1>  	;	     AH = FFh if the tty is locked by another process
  4688                              <1> 	;
  4689                              <1> 	;	  (if calling is for serial port status)
  4690                              <1> 	;	     BX = serial port status if tty number is 8 or 9
  4691                              <1> 	;		  (BH = modem status, BL = Line status)
  4692                              <1> 	;	     CX = 0FFFFh (if data is ready)
  4693                              <1> 	;	     CX = 0 (if data is not ready or undefined)		
  4694                              <1> 	;
  4695                              <1> 	;	  (if calling is for keyboard status)
  4696                              <1> 	;	     BX = current character in tty/keyboard buffer
  4697                              <1> 	;		  (BH = scan code, BL = ascii code)
  4698                              <1> 	;		  (BX=0 if there is not a waiting character)
  4699                              <1> 	;	     CX  is undefined
  4700                              <1> 	;
  4701                              <1> 	;	  (if calling is for video page status)	
  4702                              <1> 	;	     BX = cursor position on the video page
  4703                              <1> 	;		  if tty number < 8
  4704                              <1> 	;		  (BH = row, BL = column)
  4705                              <1> 	;	     CX = current character (in cursor position)
  4706                              <1> 	;		  on the video page of the tty 
  4707                              <1> 	;		  if tty number < 8
  4708                              <1> 	;		  (CH = color, CL = character)
  4709                              <1> 	;	
  4710                              <1> 	;	cf = 1 means error (requested tty is not ready)
  4711                              <1> 	;
  4712                              <1> 	;	     AH = FFh if the caller is not owner of
  4713                              <1> 	;		  specified tty or console tty
  4714                              <1> 	;	     AL = tty number (0FFh if it does not exist)
  4715                              <1> 	;	     BX, CX are undefined if cf = 1
  4716                              <1> 	;
  4717                              <1> 	;	  (If tty number is 8 or 9)
  4718                              <1> 	;	     AL = tty number 
  4719                              <1> 	;	     AH = the process number of the caller 
  4720                              <1> 	;	     BX = serial port status
  4721                              <1> 	;  		 (BH = modem status, BL = Line status)
  4722                              <1> 	;	     CX = 0
  4723                              <1> 	;
  4724                              <1> 		
  4725                              <1> gtty:   ; get (requested) tty number
  4726                              <1> 	; 26/02/2022
  4727                              <1> 	; 17/10/2015
  4728                              <1> 	; 28/06/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  4729                              <1> 	; 30/05/2013 - 12/07/2014
  4730                              <1> 	; Retro UNIX 8086 v1 modification ! 
  4731                              <1> 	;
  4732                              <1> 	; ((Modified regs: eAX, eBX, eCX, eDX, eSI, eDI, eBP))
  4733                              <1> 	;
  4734                              <1> 	; 28/06/2015 (32 bit modifications)
  4735                              <1> 	; 16/01/2014
  4736 0000427A 31C0                <1> 	xor 	eax, eax
  4737 0000427C 6648                <1> 	dec	ax ; 17/10/2015
  4738 0000427E A3[986E0000]        <1> 	mov 	[u.r0], eax ; 0FFFFh
  4739 00004283 80F901              <1> 	cmp	cl, 1
  4740 00004286 760F                <1> 	jna	short sysgtty_0
  4741                              <1> sysgtty_invp:
  4742                              <1> 	; 28/06/2015
  4743 00004288 C705[ED6E0000]1700- <1>         mov     dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
  4743 00004290 0000                <1>
  4744 00004292 E93BF8FFFF          <1> 	jmp	error
  4745                              <1> sysgtty_0:	
  4746 00004297 21DB                <1> 	and	ebx, ebx
  4747 00004299 742E                <1> 	jz	short sysgtty_1
  4748                              <1> 	;
  4749 0000429B 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  4750                              <1> 	;push	cx ; 23/11/2015
  4751 000042A1 51                  <1> 	push	ecx ; 24/12/2021
  4752 000042A2 E829070000          <1> 	call	namei
  4753 000042A7 59                  <1> 	pop	ecx
  4754                              <1> 	;pop	cx ; 23/11/2015
  4755 000042A8 7210                <1> 	jc 	short sysgtty_inv_dn ; 28/06/2015
  4756                              <1> 	;
  4757 000042AA 6683F801            <1> 	cmp	ax, 1
  4758 000042AE 7622                <1> 	jna	short sysgtty_2
  4759                              <1> 	; 26/02/2022
  4760 000042B0 20E4                <1> 	and	ah, ah
  4761 000042B2 7506                <1> 	jnz	short sysgtty_inv_dn
  4762                              <1> 	;sub	ax, 10
  4763 000042B4 2C0A                <1> 	sub	al, 10
  4764 000042B6 3C09                <1> 	cmp	al, 9
  4765                              <1> 	;cmp	ax, 9
  4766                              <1> 	;ja	short sysgtty_inv_dn
  4767                              <1> 	;mov	ch, al
  4768                              <1> 	;jmp	short sysgtty_4
  4769                              <1> 	; 23/11/2015
  4770 000042B8 7629                <1> 	jna	short sysgtty_4
  4771                              <1> sysgtty_inv_dn: 
  4772                              <1> 	; 28/06/2015
  4773                              <1> 	; Invalid device name (not a tty) ! error
  4774                              <1> 	; (Device is not a tty or device name not found)
  4775 000042BA C705[ED6E0000]1800- <1> 	mov	dword [u.error], ERR_INV_DEV_NAME
  4775 000042C2 0000                <1>
  4776 000042C4 E909F8FFFF          <1> 	jmp	error 
  4777                              <1> sysgtty_1:
  4778                              <1> 	; 16/01/2014
  4779 000042C9 80FD0A              <1> 	cmp	ch, 10
  4780 000042CC 77BA                <1> 	ja	short sysgtty_invp ; 28/06/2015
  4781 000042CE FECD                <1> 	dec	ch ; 0 -> FFh (negative)
  4782 000042D0 790F                <1> 	jns	short sysgtty_3 ; not negative
  4783                              <1> 	;
  4784                              <1> sysgtty_2:
  4785                              <1> 	; get tty number of console tty
  4786 000042D2 8A25[E76E0000]      <1> 	mov	ah, [u.uno]
  4787                              <1>  	; 28/06/2015
  4788 000042D8 0FB6DC              <1> 	movzx 	ebx, ah
  4789 000042DB 8AAB[F76B0000]      <1> 	mov	ch, [ebx+p.ttyc-1]
  4790                              <1> sysgtty_3:
  4791 000042E1 88E8                <1> 	mov	al, ch
  4792                              <1> sysgtty_4:
  4793 000042E3 A2[986E0000]        <1> 	mov	[u.r0], al
  4794                              <1>  	; 28/06/2015
  4795                              <1> 	;cmp	al, 9
  4796                              <1> 	;ja	short sysgtty_invp
  4797 000042E8 8B2D[946E0000]      <1> 	mov	ebp, [u.usp]
  4798                              <1> 	; 23/11/2015
  4799 000042EE 20C9                <1> 	and	cl, cl
  4800 000042F0 7432                <1> 	jz	short sysgtty_6 ; keyboard status
  4801 000042F2 3C08                <1> 	cmp	al, 8 ; cmp ch, 8
  4802 000042F4 722E                <1> 	jb	short sysgtty_6 ; video page status
  4803                              <1> 	; serial port status
  4804                              <1> 	; 12/07/2014
  4805                              <1> 	;mov	dx, 0
  4806                              <1> 	;je	short sysgtty_5
  4807                              <1> 	;inc	dl
  4808                              <1> ;sysgtty_5:
  4809                              <1> 	; 28/06/2015
  4810 000042F6 2C08                <1> 	sub	al, 8
  4811 000042F8 E87DF2FFFF          <1> 	call	sp_status ; serial (COM) port (line) status
  4812                              <1> 	; AL = Line status, AH = Modem status
  4813 000042FD 66894510            <1> 	mov	[ebp+16], ax ; serial port status (in EBX)
  4814 00004301 8A25[E76E0000]      <1> 	mov	ah, [u.uno]
  4815 00004307 8825[996E0000]      <1>         mov     [u.r0+1], ah
  4816                              <1> 	; 24/12/2021
  4817 0000430D 66C745180000        <1> 	mov	word [ebp+24], 0 ; data status (0 = not ready)
  4818                              <1> 				; (in ECX)
  4819 00004313 A880                <1> 	test	al, 80h
  4820 00004315 7561                <1> 	jnz	short sysgtty_dnr_err ; 29/06/2015
  4821 00004317 A801                <1> 	test	al, 1
  4822                              <1> 	;jz	sysret
  4823 00004319 7404                <1> 	jz	short sysgtty_10
  4824 0000431B 66FF4D18            <1> 	dec	word [ebp+24] ; data status (FFFFh = ready)
  4825                              <1> sysgtty_10:
  4826 0000431F E9CEF7FFFF          <1> 	jmp	sysret
  4827                              <1> sysgtty_6:
  4828 00004324 A2[EC6E0000]        <1> 	mov	[u.ttyn], al ; tty number
  4829                              <1> 	;movzx	ebx, al
  4830 00004329 88C3                <1> 	mov 	bl, al ; tty number (0 to 9)
  4831 0000432B D0E3                <1> 	shl 	bl, 1  ; aligned to word
  4832                              <1> 	; 22/04/2014 - 29/06/2015
  4833 0000432D 81C3[246B0000]      <1>         add     ebx, ttyl
  4834 00004333 8A23                <1>  	mov	ah, [ebx]
  4835 00004335 3A25[E76E0000]      <1> 	cmp	ah, [u.uno]
  4836 0000433B 7404                <1> 	je	short sysgtty_7
  4837 0000433D 20E4                <1> 	and	ah, ah
  4838                              <1> 	;jz	short sysgtty_7
  4839 0000433F 7506                <1> 	jnz	short sysgtty_8
  4840                              <1> 	;mov	ah, 0FFh
  4841                              <1> sysgtty_7:
  4842 00004341 8825[996E0000]      <1>         mov     [u.r0+1], ah
  4843                              <1> sysgtty_8:
  4844 00004347 08C9                <1> 	or	cl, cl
  4845 00004349 7510                <1> 	jnz	short sysgtty_9
  4846 0000434B B001                <1> 	mov	al, 1  ; test a key is available
  4847 0000434D E8251C0000          <1> 	call	getc
  4848 00004352 66894510            <1> 	mov	[ebp+16], ax ; bx, character
  4849 00004356 E997F7FFFF          <1> 	jmp	sysret
  4850                              <1> sysgtty_9:
  4851 0000435B 8A1D[EC6E0000]      <1> 	mov	bl, [u.ttyn]
  4852                              <1> 	; bl = video page number
  4853 00004361 E8821D0000          <1> 	call 	get_cpos
  4854                              <1> 	; dx = cursor position
  4855 00004366 66895510            <1> 	mov	[ebp+16], dx ; bx
  4856                              <1> 	;mov	bl, [u.ttyn]
  4857                              <1> 	; bl = video page number
  4858 0000436A E88A1D0000          <1> 	call	read_ac_current
  4859                              <1> 	; ax = character and attribute/color
  4860 0000436F 66894518            <1> 	mov	[ebp+24], ax ; cx
  4861 00004373 E97AF7FFFF          <1> 	jmp	sysret
  4862                              <1> sysgtty_dnr_err:
  4863                              <1> 	; 'device not responding !' error	
  4864                              <1> 	;mov 	dword [u.error], ERR_TIME_OUT ; 25
  4865 00004378 C705[ED6E0000]1900- <1> 	mov 	dword [u.error], ERR_DEV_NOT_RESP ; 25
  4865 00004380 0000                <1>
  4866 00004382 E94BF7FFFF          <1> 	jmp	error	
  4867                              <1> 
  4868                              <1> ; Original UNIX v1 'sysgtty' routine:
  4869                              <1> ; sysgtty:
  4870                              <1>         ;jsr    r0,gtty / r1 will have offset to tty block,
  4871                              <1> 	;	       / r2 has destination
  4872                              <1>         ;mov    rcsr(r1),(r2)+ / put reader control status 
  4873                              <1> 	;                     / in 1st word of dest
  4874                              <1>         ;mov    tcsr(r1),(r2)+ / put printer control status
  4875                              <1> 	;                     / in 2nd word of dest
  4876                              <1>         ;mov    tty+4(r1),(r2)+ / put mode in 3rd word
  4877                              <1>         ;jmp    sysret2 / return to user
  4878                              <1> 	
  4879                              <1> ; Original UNIX v1 'gtty' routine:
  4880                              <1> ; gtty:
  4881                              <1>         ;jsr    r0,arg; u.off / put first arg in u.off
  4882                              <1>         ;mov    *u.r0,r1 / put file descriptor in r1
  4883                              <1>         ;jsr    r0,getf / get the i-number of the file
  4884                              <1>         ;tst    r1 / is it open for reading
  4885                              <1>         ;bgt    1f / yes
  4886                              <1>         ;neg    r1 / no, i-number is negative, 
  4887                              <1> 	;          / so make it positive
  4888                              <1> ;1:
  4889                              <1>         ;sub    $14.,r1 / get i-number of tty0
  4890                              <1>         ;cmp    r1,$ntty-1 / is there such a typewriter
  4891                              <1>         ;bhis   error9 / no, error
  4892                              <1>         ;asl    r1 / 0%2
  4893                              <1>         ;asl    r1 / 0%4 / yes
  4894                              <1>         ;asl    r1 / 0%8 / multiply by 8 so r1 points to 
  4895                              <1> 	;	       ; / tty block
  4896                              <1>         ;mov    u.off,r2 / put argument in r2
  4897                              <1>         ;rts    r0 / return
  2097                                  %include 'u2.s'        ; 11/05/2015
  2098                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS2.INC
  2099                              <1> ; Last Modification: 29/04/2022
  2100                              <1> ; ----------------------------------------------------------------------------
  2101                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2102                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2103                              <1> ;
  2104                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2105                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2106                              <1> ; <Bell Laboratories (17/3/1972)>
  2107                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2108                              <1> ;
  2109                              <1> ; Retro UNIX 8086 v1 - U2.ASM (24/03/2014) //// UNIX v1 -> u2.s
  2110                              <1> ;
  2111                              <1> ; ****************************************************************************
  2112                              <1> 
  2113                              <1> syslink:
  2114                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2115                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2116                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2117                              <1> 	;
  2118                              <1> 	; 'syslink' is given two arguments, name 1 and name 2.
  2119                              <1> 	; name 1 is a file that already exists. name 2 is the name
  2120                              <1> 	; given to the entry that will go in the current directory.
  2121                              <1> 	; name2 will then be a link to the name 1 file. The i-number
  2122                              <1> 	; in the name 2 entry of current directory is the same
  2123                              <1> 	; i-number for the name 1 file.
  2124                              <1> 	;
  2125                              <1> 	; Calling sequence:
  2126                              <1> 	;	syslink; name 1; name 2
  2127                              <1> 	; Arguments:
  2128                              <1> 	;	name 1 - file name to which link will be created.
  2129                              <1> 	;	name 2 - name of entry in current directory that
  2130                              <1> 	;		 links to name 1.
  2131                              <1> 	; Inputs: -
  2132                              <1> 	; Outputs: -
  2133                              <1> 	; ...............................................................
  2134                              <1> 	;	
  2135                              <1> 	; Retro UNIX 8086 v1 modification: 
  2136                              <1> 	;       'syslink' system call has two arguments; so,
  2137                              <1> 	;	* 1st argument, name 1 is pointed to by BX register
  2138                              <1> 	;	* 2nd argument, name 2 is pointed to by CX register
  2139                              <1> 	;
  2140                              <1> 		; / name1, name2
  2141                              <1> 		;jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
  2142 00004387 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  2143 0000438D 51                  <1> 	push	ecx
  2144 0000438E E83D060000          <1> 	call	namei
  2145                              <1> 		; jsr r0,namei / find the i-number associated with
  2146                              <1> 			     ; / the 1st path name
  2147                              <1>      	;;and	ax, ax
  2148                              <1> 	;;jz	error ; File not found
  2149                              <1> 	;jc	error 
  2150                              <1> 		; br error9 / cannot be found
  2151 00004393 730F                <1> 	jnc	short syslink0
  2152                              <1> 	;pop 	ecx
  2153                              <1> 	; 'file not found !' error
  2154 00004395 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2154 0000439D 0000                <1>
  2155 0000439F E92EF7FFFF          <1> 	jmp	error
  2156                              <1> syslink0:
  2157 000043A4 E8F10D0000          <1> 	call	iget
  2158                              <1> 		; jsr r0,iget / get the i-node into core
  2159 000043A9 8F05[B06E0000]      <1> 	pop	dword [u.namep] ; ecx
  2160                              <1> 		; mov (sp)+,u.namep / u.namep points to 2nd name
  2161                              <1> 	; 24/12/2021
  2162 000043AF 50                  <1> 	push	eax ; *
  2163                              <1> 	;push	ax
  2164                              <1> 		; mov r1,-(sp) / put i-number of name1 on the stack
  2165                              <1> 			    ; / (a link to this file is to be created)
  2166                              <1> 	; 24/12/2021
  2167 000043B0 8A0D[7F6E0000]      <1> 	mov	cl, [cdev]
  2168 000043B6 51                  <1> 	push	ecx ; **
  2169                              <1> 	;push	word [cdev]
  2170                              <1> 		; mov cdev,-(sp) / put i-nodes device on the stack
  2171 000043B7 E852000000          <1> 	call	isdir
  2172                              <1> 		; jsr r0,isdir / is it a directory
  2173 000043BC E80F060000          <1> 	call	namei
  2174                              <1> 		; jsr r0,namei / no, get i-number of name2
  2175                              <1> 	;jnc	error
  2176                              <1> 		; br .+4   / not found 
  2177                              <1> 			 ; / so r1 = i-number of current directory
  2178                              <1> 			 ; / ii = i-number of current directory
  2179                              <1> 		; br error9 / file already exists., error
  2180 000043C1 720F                <1> 	jc	short syslink1
  2181                              <1> 	; pop eax ; 24/12/2021
  2182                              <1> 	; pop eax
  2183                              <1> 	; 'file exists !' error
  2184 000043C3 C705[ED6E0000]0E00- <1> 	mov	dword [u.error], ERR_FILE_EXISTS ; 14
  2184 000043CB 0000                <1>
  2185 000043CD E900F7FFFF          <1> 	jmp	error
  2186                              <1> syslink1:
  2187                              <1> 	;pop	cx
  2188                              <1> 	; 24/12/2021
  2189 000043D2 59                  <1> 	pop	ecx ; **
  2190                              <1> 	;cmp	cx, [cdev]
  2191 000043D3 3A0D[7F6E0000]      <1> 	cmp	cl, [cdev]
  2192                              <1> 	;jne	error
  2193                              <1> 		; cmp (sp)+,cdev / u.dirp now points to 
  2194                              <1> 			       ; / end of current directory
  2195                              <1> 	        ; bne error9
  2196 000043D9 740F                <1> 	je	short syslink2
  2197                              <1> 	; 'not same drive !' error
  2198 000043DB C705[ED6E0000]1500- <1> 	mov	dword [u.error],  ERR_DRV_NOT_SAME ; 21
  2198 000043E3 0000                <1>
  2199 000043E5 E9E8F6FFFF          <1> 	jmp	error
  2200                              <1> syslink2:
  2201                              <1> 	;pop	eax ; 24/12/2021
  2202                              <1> 	;push	eax
  2203                              <1> 	; 24/12/2021
  2204 000043EA 8B0424              <1> 	mov	eax, [esp] ; *
  2205 000043ED 66A3[CA6E0000]      <1> 	mov	[u.dirbuf], ax
  2206                              <1> 		; mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
  2207 000043F3 E89E000000          <1> 	call	mkdir
  2208                              <1> 		; jsr r0,mkdir / make directory entry for name2 
  2209                              <1> 		 	     ; / in current directory
  2210                              <1> 	; 24/12/2021
  2211 000043F8 58                  <1> 	pop	eax ; *
  2212                              <1> 	;pop	ax
  2213                              <1> 		; mov (sp)+,r1 / r1 has i-number of name1
  2214 000043F9 E89C0D0000          <1> 	call	iget
  2215                              <1> 		; jsr r0,iget / get i-node into core
  2216 000043FE FE05[9A6B0000]      <1> 	inc	byte [i.nlks]
  2217                              <1> 		; incb i.nlks / add 1 to its number of links
  2218 00004404 E89B0E0000          <1> 	call	setimod
  2219                              <1> 		; jsr r0,setimod / set the i-node modified flag
  2220 00004409 E9E4F6FFFF          <1> 	jmp	sysret
  2221                              <1> 
  2222                              <1> isdir:
  2223                              <1> 	; 03/02/2022
  2224                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  2225                              <1> 	; 04/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  2226                              <1> 	;
  2227                              <1> 	; 'isdir' check to see if the i-node whose i-number is in r1
  2228                              <1> 	;  is a directory. If it is, an error occurs, because 'isdir'
  2229                              <1> 	;  called by syslink and sysunlink to make sure directories
  2230                              <1> 	;  are not linked. If the user is the super user (u.uid=0),
  2231                              <1> 	; 'isdir' does not bother checking. The current i-node
  2232                              <1> 	;  is not disturbed.			
  2233                              <1> 	;		
  2234                              <1> 	; INPUTS ->
  2235                              <1> 	;    r1 - contains the i-number whose i-node is being checked.
  2236                              <1> 	;    u.uid - user id
  2237                              <1> 	; OUTPUTS ->
  2238                              <1> 	;    r1 - contains current i-number upon exit
  2239                              <1> 	;    	 (current i-node back in core) 
  2240                              <1> 	;	
  2241                              <1> 	; ((AX = R1))
  2242                              <1> 	;
  2243                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2244                              <1> 	;
  2245                              <1> 
  2246                              <1> 	; / if the i-node whose i-number is in r1 is a directory 
  2247                              <1> 	; / there is an error unless super user made the call
  2248                              <1> 	
  2249 0000440E 803D[E46E0000]00    <1> 	cmp	byte [u.uid], 0 
  2250                              <1> 		; tstb u.uid / super user
  2251 00004415 762B                <1> 	jna	short isdir1
  2252                              <1> 		; beq 1f / yes, don't care
  2253 00004417 66FF35[7C6E0000]    <1> 	push	word [ii]
  2254                              <1> 		; mov ii,-(sp) / put current i-number on stack
  2255 0000441E E8770D0000          <1> 	call	iget
  2256                              <1> 		; jsr r0,iget / get i-node into core (i-number in r1)
  2257                              <1> 	; 03/02/2022
  2258 00004423 F605[996B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2259                              <1> 	;test 	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2260                              <1> 		; bit $40000,i.flgs / is it a directory
  2261                              <1> 	;jnz	error
  2262                              <1> 		; bne error9 / yes, error
  2263 0000442A 740F                <1> 	jz	short isdir0
  2264 0000442C C705[ED6E0000]0B00- <1> 	mov 	dword [u.error], ERR_NOT_FILE  ; 11 ; ERR_DIR_ACCESS 
  2264 00004434 0000                <1>
  2265                              <1> 				; 'permission denied !' error
  2266                              <1> 	; pop	ax
  2267 00004436 E997F6FFFF          <1> 	jmp	error	
  2268                              <1> isdir0:	
  2269 0000443B 6658                <1> 	pop	ax
  2270                              <1> 		; mov (sp)+,r1 / no, put current i-number in r1 (ii)
  2271 0000443D E8580D0000          <1> 	call	iget
  2272                              <1> 		; jsr r0,iget / get it back in
  2273                              <1> isdir1: ; 1:
  2274 00004442 C3                  <1> 	retn
  2275                              <1> 		; rts r0
  2276                              <1> 
  2277                              <1> sysunlink:
  2278                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2279                              <1> 	; 04/12/2015 (14 byte file names)
  2280                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2281                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  2282                              <1> 	;
  2283                              <1> 	; 'sysunlink' removes the entry for the file pointed to by
  2284                              <1> 	; name from its directory. If this entry was the last link
  2285                              <1> 	; to the file, the contents of the file are freed and the
  2286                              <1> 	; file is destroyed. If, however, the file was open in any
  2287                              <1> 	; process, the actual destruction is delayed until it is 
  2288                              <1> 	; closed, even though the directory entry has disappeared.
  2289                              <1> 	; 
  2290                              <1> 	; The error bit (e-bit) is set to indicate that the file	
  2291                              <1> 	; does not exist or that its directory can not be written.
  2292                              <1> 	; Write permission is not required on the file itself.
  2293                              <1> 	; It is also illegal to unlink a directory (except for
  2294                              <1> 	; the superuser).
  2295                              <1> 	;
  2296                              <1> 	; Calling sequence:
  2297                              <1> 	;	sysunlink; name
  2298                              <1> 	; Arguments:
  2299                              <1> 	;	name - name of directory entry to be removed 
  2300                              <1> 	; Inputs: -
  2301                              <1> 	; Outputs: -
  2302                              <1> 	; ...............................................................
  2303                              <1> 	;				
  2304                              <1> 	; Retro UNIX 8086 v1 modification:
  2305                              <1> 	;	 The user/application program puts address of the name
  2306                              <1> 	;        in BX register as 'sysunlink' system call argument.
  2307                              <1> 
  2308                              <1> 	; / name - remove link name
  2309 00004443 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  2310                              <1> 		;jsr r0,arg; u.namep / u.namep points to name
  2311 00004449 E882050000          <1> 	call	namei
  2312                              <1> 		; jsr r0,namei / find the i-number associated 
  2313                              <1> 			     ; / with the path name
  2314                              <1> 	;jc	error
  2315                              <1> 		; br error9 / not found
  2316 0000444E 730F                <1> 	jnc	short sysunlink1
  2317                              <1> 	; 'file not found !' error
  2318 00004450 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  2318 00004458 0000                <1>
  2319 0000445A E973F6FFFF          <1> 	jmp	error
  2320                              <1> sysunlink1:
  2321 0000445F 50                  <1> 	push	eax ; 24/12/2021
  2322                              <1> 	;push	ax
  2323                              <1> 		; mov r1,-(sp) / put its i-number on the stack
  2324 00004460 E8A9FFFFFF          <1> 	call	isdir
  2325                              <1> 		; jsr r0,isdir / is it a directory
  2326                              <1> 	;xor 	ax, ax
  2327                              <1> 	; 24/12/2021
  2328 00004465 31C0                <1> 	xor	eax, eax
  2329 00004467 66A3[CA6E0000]      <1> 	mov	[u.dirbuf], ax ; 0
  2330                              <1> 		; clr u.dirbuf / no, clear the location that will
  2331                              <1> 			   ; / get written into the i-number portion
  2332                              <1> 			 ; / of the entry
  2333 0000446D 832D[B46E0000]10    <1> 	sub	dword [u.off], 16 ; 04/12/2015 (10 -> 16) 
  2334                              <1> 		; sub $10.,u.off / move u.off back 1 directory entry
  2335 00004474 E868000000          <1> 	call	wdir
  2336                              <1> 		; jsr r0,wdir / free the directory entry
  2337 00004479 58                  <1> 	pop	eax ; 24/12/2021
  2338                              <1> 	;pop	ax
  2339                              <1> 		; mov (sp)+,r1 / get i-number back
  2340 0000447A E81B0D0000          <1> 	call	iget
  2341                              <1> 		; jsr r0,iget / get i-node
  2342 0000447F E8200E0000          <1> 	call	setimod
  2343                              <1> 		; jsr r0,setimod / set modified flag
  2344 00004484 FE0D[9A6B0000]      <1> 	dec	byte [i.nlks]
  2345                              <1> 		; decb i.nlks / decrement the number of links
  2346                              <1> 	; 24/12/2021
  2347 0000448A 7505                <1> 	jnz	short sysunlink_2
  2348                              <1> 	;jnz	sysret
  2349                              <1> 		; bgt sysret9 / if this was not the last link
  2350                              <1> 			    ; / to file return
  2351                              <1> 	; AX = r1 = i-number
  2352 0000448C E85E090000          <1> 	call	anyi
  2353                              <1> 		; jsr r0,anyi / if it was, see if anyone has it open.
  2354                              <1> 			 ; / Then free contents of file and destroy it.
  2355                              <1> sysunlink_2:
  2356 00004491 E95CF6FFFF          <1> 	jmp	sysret
  2357                              <1> 		; br sysret9
  2358                              <1> 
  2359                              <1> mkdir:
  2360                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2361                              <1> 	; 04/12/2015 (14 byte directory names)
  2362                              <1> 	; 12/10/2015
  2363                              <1> 	; 17/06/2015 (Retro UNIX 386 v1 - Beginning)
  2364                              <1> 	; 29/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2365                              <1> 	;
  2366                              <1> 	; 'mkdir' makes a directory entry from the name pointed to
  2367                              <1> 	; by u.namep into the current directory.
  2368                              <1> 	;
  2369                              <1> 	; INPUTS ->
  2370                              <1> 	;    u.namep - points to a file name 
  2371                              <1> 	;	           that is about to be a directory entry.
  2372                              <1> 	;    ii - current directory's i-number.	
  2373                              <1> 	; OUTPUTS ->
  2374                              <1> 	;    u.dirbuf+2 - u.dirbuf+10 - contains file name. 
  2375                              <1> 	;    u.off - points to entry to be filled 
  2376                              <1> 	;	     in the current directory		
  2377                              <1> 	;    u.base - points to start of u.dirbuf.
  2378                              <1> 	;    r1 - contains i-number of current directory 
  2379                              <1> 	;	
  2380                              <1> 	; ((AX = R1)) output
  2381                              <1> 	;
  2382                              <1> 	;    (Retro UNIX Prototype : 11/11/2012, UNIXCOPY.ASM)
  2383                              <1>         ;    ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  2384                              <1> 	;
  2385                              <1> 
  2386                              <1> 	; 17/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  2387 00004496 31C0                <1> 	xor 	eax, eax
  2388 00004498 BF[CC6E0000]        <1> 	mov     edi, u.dirbuf+2
  2389 0000449D 89FE                <1> 	mov	esi, edi
  2390 0000449F AB                  <1> 	stosd
  2391 000044A0 AB                  <1> 	stosd
  2392                              <1> 	; 04/12/2015 (14 byte directory names)
  2393 000044A1 AB                  <1> 	stosd
  2394 000044A2 66AB                <1> 	stosw
  2395                              <1> 		; jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
  2396 000044A4 89F7                <1> 	mov	edi, esi ; offset to u.dirbuf
  2397                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2398                              <1> 	;mov 	ebp, [u.namep]
  2399 000044A6 E85E060000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  2400                              <1> 		; esi = physical address (page start + offset)
  2401                              <1> 		; ecx = byte count in the page (1 - 4096)
  2402                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2403                              <1> 		; mov u.namep,r2 / r2 points to name of directory entry
  2404                              <1> 		; mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
  2405                              <1> mkdir_1: ; 1: 
  2406 000044AB 45                  <1> 	inc	ebp ; 12/10/2015
  2407                              <1> 	;
  2408                              <1> 	; / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
  2409                              <1> 	 ; 01/08/2013
  2410 000044AC AC                  <1> 	lodsb
  2411                              <1> 		; movb (r2)+,r1 / move character in name to r1
  2412 000044AD 20C0                <1> 	and 	al, al
  2413 000044AF 7426                <1> 	jz 	short mkdir_3 	  
  2414                              <1> 		; beq 1f / if null, done
  2415 000044B1 3C2F                <1> 	cmp	al, '/'
  2416                              <1> 		; cmp r1,$'/ / is it a "/"?
  2417 000044B3 7413                <1> 	je	short mkdir_err
  2418                              <1> 	;je	error
  2419                              <1> 		; beq error9 / yes, error
  2420                              <1> 	; 12/10/2015
  2421                              <1> 	;dec	cx
  2422 000044B5 49                  <1> 	dec	ecx ; 24/12/2021
  2423 000044B6 7505                <1> 	jnz	short mkdir_2
  2424                              <1> 	; 12/10/2015 ([u.namep] -> ebp)
  2425 000044B8 E852060000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  2426                              <1> 		; esi = physical address (page start + offset)
  2427                              <1> 		; ecx = byte count in the page
  2428                              <1> 	; edi = offset to u.dirbuf (edi is not modified in trans_addr_nm)
  2429                              <1> mkdir_2:
  2430 000044BD 81FF[DA6E0000]      <1> 	cmp     edi, u.dirbuf+16 ; ; 04/12/2015 (10 -> 16) 
  2431                              <1> 		; cmp r3,$u.dirbuf+10. / have we reached the last slot for
  2432                              <1> 				     ; / a char?
  2433 000044C3 74E6                <1> 	je	short mkdir_1
  2434                              <1> 		; beq 1b / yes, go back
  2435 000044C5 AA                  <1> 	stosb
  2436                              <1> 		; movb r1,(r3)+ / no, put the char in the u.dirbuf
  2437 000044C6 EBE3                <1> 	jmp 	short mkdir_1
  2438                              <1> 		; br 1b / get next char
  2439                              <1> mkdir_err:
  2440                              <1> 	; 17/06/2015
  2441 000044C8 C705[ED6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  2441 000044D0 0000                <1>
  2442 000044D2 E9FBF5FFFF          <1> 	jmp	error
  2443                              <1> 
  2444                              <1> mkdir_3: ; 1:
  2445 000044D7 A1[AC6E0000]        <1> 	mov	eax, [u.dirp]
  2446 000044DC A3[B46E0000]        <1> 	mov	[u.off], eax
  2447                              <1> 		; mov u.dirp,u.off / pointer to empty current directory
  2448                              <1> 				 ; / slot to u.off
  2449                              <1> wdir: 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2450                              <1> 	; 29/04/2013
  2451 000044E1 C705[B86E0000]-     <1>         mov     dword [u.base], u.dirbuf
  2451 000044E7 [CA6E0000]          <1>
  2452                              <1> 		; mov $u.dirbuf,u.base / u.base points to created file name
  2453 000044EB C705[BC6E0000]1000- <1>         mov     dword [u.count], 16 ; 04/12/2015 (10 -> 16) 
  2453 000044F3 0000                <1>
  2454                              <1> 		; mov $10.,u.count / u.count = 10
  2455 000044F5 66A1[7C6E0000]      <1> 	mov	ax, [ii] 
  2456                              <1> 		; mov ii,r1 / r1 has i-number of current directory
  2457 000044FB B201                <1> 	mov	dl, 1 ; owner flag mask ; RETRO UNIX 8086 v1 modification !
  2458 000044FD E86C0D0000          <1> 	call 	access
  2459                              <1> 		; jsr r0,access; 1 / get i-node and set its file up 
  2460                              <1> 				 ; / for writing
  2461                              <1> 	; AX = i-number of current directory
  2462                              <1> 	; 01/08/2013
  2463 00004502 FE05[FF6E0000]      <1> 	inc     byte [u.kcall] ; the caller is 'mkdir' sign	
  2464                              <1> 	;call	writei
  2465                              <1> 	;	; jsr r0,writei / write into directory
  2466                              <1> 	;retn	
  2467                              <1> 	;	; rts r0
  2468                              <1> 	; 24/12/2021
  2469 00004508 E94F100000          <1> 	jmp	writei
  2470                              <1> 
  2471                              <1> sysexec:
  2472                              <1> 	; 03/02/2022
  2473                              <1> 	; 12/01/2022
  2474                              <1> 	; 08/01/2022
  2475                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2476                              <1> 	; 23/10/2015
  2477                              <1> 	; 19/10/2015
  2478                              <1> 	; 10/10/2015, 18/10/2015
  2479                              <1> 	; 29/07/2015, 05/08/2015, 26/08/2015
  2480                              <1> 	; 21/07/2015, 24/07/2015, 25/07/2015
  2481                              <1> 	; 01/07/2015, 02/07/2015, 20/07/2015
  2482                              <1> 	; 24/06/2015, 25/06/2015
  2483                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  2484                              <1> 	; 03/06/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2485                              <1> 	;
  2486                              <1> 	; 'sysexec' initiates execution of a file whose path name if
  2487                              <1> 	; pointed to by 'name' in the sysexec call. 
  2488                              <1> 	; 'sysexec' performs the following operations:
  2489                              <1> 	;    1. obtains i-number of file to be executed via 'namei'.
  2490                              <1> 	;    2. obtains i-node of file to be exceuted via 'iget'.
  2491                              <1> 	;    3. sets trap vectors to system routines.
  2492                              <1> 	;    4. loads arguments to be passed to executing file into
  2493                              <1> 	;	highest locations of user's core
  2494                              <1> 	;    5. puts pointers to arguments in locations immediately
  2495                              <1> 	;	following arguments.
  2496                              <1> 	;    6.	saves number of arguments in next location.
  2497                              <1> 	;    7. initializes user's stack area so that all registers
  2498                              <1> 	;	will be zeroed and the PS is cleared and the PC set
  2499                              <1> 	;	to core when 'sysret' restores registers 
  2500                              <1> 	;	and does an rti.
  2501                              <1> 	;    8. inializes u.r0 and u.sp
  2502                              <1> 	;    9. zeros user's core down to u.r0
  2503                              <1> 	;   10.	reads executable file from storage device into core
  2504                              <1> 	;	starting at location 'core'.
  2505                              <1> 	;   11.	sets u.break to point to end of user's code with
  2506                              <1> 	;	data area appended.
  2507                              <1> 	;   12.	calls 'sysret' which returns control at location
  2508                              <1> 	;	'core' via 'rti' instruction. 		  		
  2509                              <1> 	;
  2510                              <1> 	; Calling sequence:
  2511                              <1> 	;	sysexec; namep; argp
  2512                              <1> 	; Arguments:
  2513                              <1> 	;	namep - points to pathname of file to be executed
  2514                              <1> 	;	argp  - address of table of argument pointers
  2515                              <1> 	;	argp1... argpn - table of argument pointers
  2516                              <1> 	;	argp1:<...0> ... argpn:<...0> - argument strings
  2517                              <1> 	; Inputs: (arguments)
  2518                              <1> 	; Outputs: -	
  2519                              <1> 	; ...............................................................
  2520                              <1> 	;
  2521                              <1> 	; Retro UNIX 386 v1 modification: 
  2522                              <1> 	;	User application runs in it's own virtual space 
  2523                              <1> 	;	which is izolated from kernel memory (and other
  2524                              <1> 	;	memory pages) via 80386	paging in ring 3 
  2525                              <1> 	;	privilige mode. Virtual start address is always 0.
  2526                              <1> 	;	User's core memory starts at linear address 400000h
  2527                              <1> 	;	(the end of the 1st 4MB).
  2528                              <1> 	;
  2529                              <1> 	; Retro UNIX 8086 v1 modification: 
  2530                              <1> 	;	user/application segment and system/kernel segment
  2531                              <1> 	;	are different and sysenter/sysret/sysrele routines
  2532                              <1> 	;	are different (user's registers are saved to 
  2533                              <1> 	;	and then restored from system's stack.)
  2534                              <1> 	;
  2535                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  2536                              <1> 	;	      arguments which were in these registers;
  2537                              <1> 	;	      but, it returns by putting the 1st argument
  2538                              <1> 	;	      in 'u.namep' and the 2nd argument
  2539                              <1> 	;	      on top of stack. (1st argument is offset of the
  2540                              <1> 	;	      file/path name in the user's program segment.)		 	
  2541                              <1> 	
  2542                              <1> 	;call	arg2
  2543                              <1> 	; * name - 'u.namep' points to address of file/path name
  2544                              <1> 	;          in the user's program segment ('u.segmnt')
  2545                              <1> 	;          with offset in BX register (as sysopen argument 1).
  2546                              <1> 	; * argp - sysexec argument 2 is in CX register 
  2547                              <1> 	;          which is on top of stack.
  2548                              <1> 	;
  2549                              <1> 		; jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
  2550                              <1> 
  2551                              <1> 	; 23/06/2015 (32 bit modifications)
  2552                              <1> 
  2553 0000450D 891D[B06E0000]      <1> 	mov	[u.namep], ebx ; argument 1
  2554                              <1>         ; 18/10/2015
  2555 00004513 890D[186F0000]      <1> 	mov     [argv], ecx  ; * ; argument 2
  2556 00004519 E8B2040000          <1> 	call	namei
  2557                              <1> 		; jsr r0,namei / namei returns i-number of file 
  2558                              <1> 			     ; / named in sysexec call in r1
  2559                              <1> 	;jc	error
  2560                              <1> 		; br error9
  2561 0000451E 731E                <1> 	jnc	short sysexec_0
  2562                              <1> 	;
  2563                              <1> 	; 'file not found !' error
  2564 00004520 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND
  2564 00004528 0000                <1>
  2565 0000452A E9A3F5FFFF          <1> 	jmp	error 
  2566                              <1> sysexec_not_exf:
  2567                              <1> 	; 'not executable file !' error
  2568 0000452F C705[ED6E0000]1600- <1> 	mov	dword [u.error], ERR_NOT_EXECUTABLE
  2568 00004537 0000                <1>
  2569 00004539 E994F5FFFF          <1> 	jmp	error 
  2570                              <1> sysexec_0:
  2571 0000453E E8570C0000          <1> 	call	iget
  2572                              <1> 		; jsr r0,iget / get i-node for file to be executed
  2573                              <1> 	; 24/12/2021
  2574 00004543 F605[986B0000]10    <1> 	test	byte [i.flgs], 10h
  2575                              <1> 	;test	word [i.flgs], 10h
  2576                              <1> 	;	; bit $20,i.flgs / is file executable
  2577 0000454A 74E3                <1> 	jz	short sysexec_not_exf
  2578                              <1> 	;jz	error
  2579                              <1> 		; beq error9
  2580                              <1> 	;;
  2581 0000454C E8CD130000          <1> 	call	iopen
  2582                              <1> 		; jsr r0,iopen / gets i-node for file with i-number
  2583                              <1> 			     ; / given in r1 (opens file)
  2584                              <1> 	; AX = i-number of the file
  2585                              <1> 	; 24/12/2021
  2586 00004551 F605[986B0000]20    <1> 	test	byte [i.flgs], 20h
  2587                              <1> 	;test	word [i.flgs], 20h
  2588                              <1> 		; bit $40,i.flgs / test user id on execution bit
  2589 00004558 7415                <1> 	jz	short sysexec_1
  2590                              <1> 		; beq 1f
  2591 0000455A 803D[E46E0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013
  2592                              <1> 		; tstb u.uid / test user id
  2593 00004561 760C                <1> 	jna	short sysexec_1
  2594                              <1> 		; beq 1f / super user
  2595 00004563 8A0D[9B6B0000]      <1> 	mov	cl, [i.uid]
  2596 00004569 880D[E46E0000]      <1> 	mov	[u.uid], cl ; 02/08/2013
  2597                              <1> 		; movb i.uid,u.uid / put user id of owner of file
  2598                              <1> 				 ; / as process user id
  2599                              <1> sysexec_1:
  2600                              <1> 	; 03/02/2022
  2601                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2602                              <1> 	; 18/10/2215
  2603                              <1> 	; 10/10/2015
  2604                              <1> 	; 21/07/2015, 24/07/2015
  2605                              <1> 	; 24/06/2015, 25/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 0000456F 89E5                <1> 	mov	ebp, esp ; (**)
  2612                              <1> 	; 18/10/2015
  2613 00004571 89EF                <1> 	mov 	edi, ebp
  2614 00004573 B900010000          <1> 	mov 	ecx, MAX_ARG_LEN ; 256
  2615                              <1> 	;sub	edi, MAX_ARG_LEN ; 256
  2616 00004578 29CF                <1> 	sub	edi, ecx
  2617 0000457A 89FC                <1> 	mov	esp, edi
  2618 0000457C 31C0                <1> 	xor	eax, eax
  2619 0000457E A3[C06E0000]        <1> 	mov 	[u.nread], eax ; 0
  2620                              <1> 	; 12/01/2022
  2621                              <1> 	; ([argc] must be cleared because previous 'sysexec'
  2622                              <1> 	; may leave it with any value after an error))
  2623                              <1> 	;mov	[argc], ax
  2624 00004583 A2[166F0000]        <1> 	mov	[argc], al ; 0
  2625                              <1> 	;
  2626 00004588 49                  <1> 	dec	ecx ; 256 - 1
  2627 00004589 890D[BC6E0000]      <1> 	mov 	[u.count], ecx ; MAX_ARG_LEN - 1 ; 255
  2628                              <1> 	;mov 	dword [u.count], MAX_ARG_LEN - 1 ; 255
  2629                              <1> sysexec_2:
  2630 0000458F 8B35[186F0000]      <1> 	mov	esi, [argv] ; 18/10/2015 
  2631 00004595 E860020000          <1> 	call	get_argp
  2632                              <1> 	;mov	ecx, 4 
  2633                              <1> 	; 03/02/2022
  2634 0000459A 31C9                <1> 	xor	ecx, ecx
  2635 0000459C B104                <1> 	mov	cl, 4
  2636                              <1> sysexec_3:
  2637 0000459E 21C0                <1> 	and	eax, eax
  2638 000045A0 7455                <1> 	jz	short sysexec_6
  2639                              <1> 	; 18/10/2015
  2640 000045A2 010D[186F0000]      <1> 	add	[argv], ecx ; 4
  2641                              <1> 	;inc	word [argc]
  2642                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2643 000045A8 FE05[166F0000]      <1> 	inc	byte [argc]
  2644                              <1> 	;
  2645 000045AE A3[B86E0000]        <1> 	mov	[u.base], eax
  2646                              <1>  	; 23/10/2015
  2647 000045B3 66C705[FD6E0000]00- <1> 	mov	word [u.pcount], 0
  2647 000045BB 00                  <1>
  2648                              <1> sysexec_4:
  2649 000045BC E850110000          <1> 	call	cpass ; get a character from user's core memory
  2650 000045C1 750B                <1>         jnz	short sysexec_5
  2651                              <1> 		; (max. 255 chars + null)
  2652                              <1> 	; 18/10/2015
  2653 000045C3 28C0                <1> 	sub 	al, al
  2654 000045C5 AA                  <1> 	stosb
  2655 000045C6 FF05[C06E0000]      <1> 	inc	dword [u.nread]
  2656 000045CC EB29                <1> 	jmp	short sysexec_6
  2657                              <1> sysexec_5:
  2658 000045CE AA                  <1> 	stosb
  2659 000045CF 20C0                <1> 	and 	al, al
  2660 000045D1 75E9                <1> 	jnz	short sysexec_4
  2661                              <1> 	;mov	ecx, 4
  2662                              <1> 	; 24/12/2021
  2663 000045D3 29C9                <1> 	sub	ecx, ecx
  2664 000045D5 B104                <1> 	mov	cl, 4
  2665                              <1> 	;cmp	[ncount], ecx ; 4
  2666                              <1> 	; 24/12/2021
  2667 000045D7 66390D[146F0000]    <1> 	cmp	[ncount], cx ; 4
  2668 000045DE 72AF                <1> 	jb	short sysexec_2
  2669 000045E0 8B35[106F0000]      <1> 	mov	esi, [nbase]
  2670 000045E6 010D[106F0000]      <1> 	add	[nbase], ecx ; 4	
  2671 000045EC 66290D[146F0000]    <1> 	sub	[ncount], cx 
  2672 000045F3 8B06                <1> 	mov	eax, [esi]
  2673 000045F5 EBA7                <1> 	jmp	short sysexec_3
  2674                              <1> sysexec_6:
  2675                              <1> 	; 18/10/2015
  2676                              <1> 	; argument list transfer from user's core memory to
  2677                              <1> 	; kernel stack frame is OK here.
  2678                              <1> 	; [u.nread] = ; argument list length
  2679                              <1> 	;mov	[argv], esp ; start address of argument list 	
  2680                              <1> 	;
  2681                              <1> 	; 18/10/2015
  2682                              <1> 	; 24/07/2015
  2683                              <1>         ; 21/07/2015
  2684                              <1> 	; 02/07/2015
  2685                              <1> 	; 25/06/2015
  2686                              <1> 	; 24/06/2015
  2687                              <1> 	; 23/06/2015
  2688                              <1> 	;
  2689 000045F7 8B1D[F56E0000]      <1> 	mov	ebx, [u.ppgdir] ; parent's page directory
  2690 000045FD 21DB                <1> 	and 	ebx, ebx  ; /etc/init ? (u.ppgdir = 0)	
  2691 000045FF 740A                <1> 	jz	short sysexec_7
  2692 00004601 A1[F16E0000]        <1> 	mov	eax, [u.pgdir] ; physical address of page directory
  2693 00004606 E8DBE8FFFF          <1> 	call	deallocate_page_dir
  2694                              <1> sysexec_7:
  2695 0000460B E80BE8FFFF          <1> 	call	make_page_dir
  2696                              <1> 	;jc	short sysexec_14
  2697                              <1> 	;jc	panic  ; allocation error 
  2698                              <1> 		       ; after a deallocation would be nonsence !?
  2699                              <1> 	; 08/01/2022
  2700 00004610 7243                <1> 	jc	short sysexec_panic
  2701                              <1> 
  2702                              <1> 	; 24/07/2015
  2703                              <1> 	; map kernel pages (1st 4MB) to PDE 0
  2704                              <1> 	;     of the user's page directory
  2705                              <1> 	;     (It is needed for interrupts!)
  2706                              <1> 	; 18/10/2015
  2707 00004612 8B15[D86A0000]      <1> 	mov	edx, [k_page_dir] ; Kernel's page directory
  2708 00004618 8B02                <1> 	mov	eax, [edx] ; physical address of
  2709                              <1> 			   ; kernel's first page table (1st 4 MB)
  2710                              <1> 			   ; (PDE 0 of kernel's page directory)
  2711 0000461A 8B15[F16E0000]      <1> 	mov 	edx, [u.pgdir]
  2712 00004620 8902                <1> 	mov	[edx], eax ; PDE 0 (1st 4MB)
  2713                              <1> 	;
  2714                              <1> 	; 20/07/2015
  2715 00004622 BB00004000          <1> 	mov	ebx, CORE ; start address = 0 (virtual) + CORE
  2716                              <1> 	; 18/10/2015
  2717 00004627 BE[086F0000]        <1> 	mov	esi, pcore ; physical start address
  2718                              <1> sysexec_8:	
  2719 0000462C B907000000          <1> 	mov	ecx, PDE_A_USER + PDE_A_WRITE + PDE_A_PRESENT
  2720 00004631 E803E8FFFF          <1> 	call	make_page_table
  2721                              <1> 	;jc	panic
  2722                              <1> 	; 24/12/2021
  2723 00004636 721D                <1> 	jc	short sysexec_panic
  2724                              <1> 	;mov	ecx, PTE_A_USER + PTE_A_WRITE + PTE_A_PRESENT
  2725 00004638 E80AE8FFFF          <1> 	call	make_page ; make new page, clear and set the pte 
  2726                              <1> 	;jc	panic
  2727                              <1> 	; 24/12/2021
  2728 0000463D 7216                <1> 	jc	short sysexec_panic
  2729                              <1> 	;
  2730 0000463F 8906                <1> 	mov	[esi], eax ; 24/06/2015
  2731                              <1> 	; ebx = virtual address (24/07/2015)
  2732                              <1> 	; 24/12/2021
  2733                              <1> 	;call 	add_to_swap_queue
  2734                              <1> 	; 18/10/2015
  2735 00004641 81FE[0C6F0000]      <1> 	cmp	esi, ecore ; user's stack (last) page ?
  2736 00004647 7411                <1> 	je	short sysexec_9 ; yes
  2737 00004649 BE[0C6F0000]        <1> 	mov	esi, ecore  ; physical address of the last page 
  2738                              <1> 	; 20/07/2015
  2739 0000464E BB00F0FFFF          <1> 	mov	ebx, (ECORE - PAGE_SIZE) + CORE
  2740                              <1> 	; ebx = virtual end address + segment base address - 4K
  2741 00004653 EBD7                <1>         jmp     short sysexec_8
  2742                              <1> 
  2743                              <1> sysexec_panic:
  2744                              <1> 	; 26/03/2021
  2745 00004655 E92CEDFFFF          <1> 	jmp	panic
  2746                              <1> 
  2747                              <1> sysexec_9:
  2748                              <1> 	; 18/10/2015
  2749                              <1> 	; 26/08/2015
  2750                              <1> 	; 25/06/2015
  2751                              <1> 	; move arguments from kernel stack to [ecore]
  2752                              <1> 	; (argument list/line will be copied from kernel stack
  2753                              <1> 	; frame to the last (stack) page of user's core memory)
  2754                              <1> 	; 18/10/2015
  2755 0000465A 8B3D[0C6F0000]      <1> 	mov	edi, [ecore]
  2756 00004660 81C700100000        <1> 	add	edi, PAGE_SIZE
  2757                              <1> 	;movzx	eax, word [argc]
  2758                              <1> 	; 12/01/2022
  2759 00004666 31C0                <1> 	xor	eax, eax
  2760 00004668 A0[166F0000]        <1> 	mov	al, [argc]
  2761 0000466D 08C0                <1> 	or	al, al
  2762                              <1> 	;or	eax, eax
  2763 0000466F 7509                <1> 	jnz	short sysexec_10
  2764 00004671 89FB                <1> 	mov 	ebx, edi
  2765 00004673 83EB04              <1> 	sub	ebx, 4 
  2766 00004676 8903                <1> 	mov	[ebx], eax ; 0
  2767 00004678 EB40                <1> 	jmp 	short sysexec_13
  2768                              <1> sysexec_10:
  2769 0000467A 8B0D[C06E0000]      <1> 	mov	ecx, [u.nread]
  2770                              <1> 	;mov 	esi, [argv]
  2771 00004680 89E6                <1> 	mov	esi, esp ; start address of argument list
  2772 00004682 29CF                <1> 	sub	edi, ecx ; page end address - argument list length
  2773 00004684 89C2                <1> 	mov	edx, eax
  2774                              <1> 	; 12/01/2022 ; ([argc] < 32)
  2775 00004686 FEC2                <1> 	inc	dl ; argument count + 1 for argc value  
  2776 00004688 C0E202              <1> 	shl 	dl, 2  ; 4 * (argument count + 1)
  2777                              <1> 	; edx <= 128
  2778 0000468B 89FB                <1> 	mov	ebx, edi
  2779 0000468D 80E3FC              <1> 	and	bl, 0FCh ; 32 bit (dword) alignment
  2780 00004690 29D3                <1> 	sub 	ebx, edx
  2781 00004692 89FA                <1> 	mov	edx, edi
  2782 00004694 F3A4                <1> 	rep	movsb
  2783 00004696 89D6                <1> 	mov 	esi, edx
  2784 00004698 89DF                <1> 	mov 	edi, ebx
  2785 0000469A BA00F0BFFF          <1> 	mov	edx, ECORE - PAGE_SIZE ; virtual addr. of the last page
  2786 0000469F 2B15[0C6F0000]      <1> 	sub 	edx, [ecore] ; difference (virtual - physical) 
  2787 000046A5 AB                  <1> 	stosd	; eax = argument count	
  2788                              <1> sysexec_11:
  2789 000046A6 89F0                <1> 	mov	eax, esi
  2790 000046A8 01D0                <1> 	add	eax, edx
  2791 000046AA AB                  <1> 	stosd  ; eax = virtual address
  2792 000046AB FE0D[166F0000]      <1> 	dec	byte [argc]
  2793 000046B1 7407                <1> 	jz	short sysexec_13
  2794                              <1> sysexec_12:
  2795 000046B3 AC                  <1> 	lodsb
  2796 000046B4 20C0                <1> 	and	al, al
  2797 000046B6 75FB                <1> 	jnz	short sysexec_12
  2798 000046B8 EBEC                <1> 	jmp	short sysexec_11
  2799                              <1> 	;
  2800                              <1> 	; 1:
  2801                              <1> 		; mov (sp)+,r5 / r5 now contains address of list of 
  2802                              <1> 			     ; / pointers to arguments to be passed
  2803                              <1> 		; mov $1,u.quit / u.quit determines handling of quits;
  2804                              <1> 			      ; / u.quit = 1 take quit
  2805                              <1> 		; mov $1,u.intr / u.intr determines handling of 
  2806                              <1> 			     ; / interrupts; u.intr = 1 take interrupt
  2807                              <1> 		; mov $rtssym,30 / emt trap vector set to take 
  2808                              <1> 			       ; / system routine
  2809                              <1> 		; mov $fpsym,*10 / reserved instruction trap vector 
  2810                              <1> 			       ; / set to take system routine
  2811                              <1> 		; mov $sstack,sp / stack space used during swapping
  2812                              <1> 		; mov r5,-(sp) / save arguments pointer on stack
  2813                              <1> 		; mov $ecore,r5 / r5 has end of core
  2814                              <1> 		; mov $core,r4 / r4 has start of users core
  2815                              <1> 		; mov r4,u.base / u.base has start of users core
  2816                              <1> 		; mov (sp),r2 / move arguments list pointer into r2
  2817                              <1> 	; 1:
  2818                              <1> 		; tst (r2)+ / argument char = "nul"
  2819                              <1> 		; bne 1b
  2820                              <1> 		; tst -(r2) / decrement r2 by 2; r2 has addr of 
  2821                              <1> 			  ; / end of argument pointer list
  2822                              <1> 	; 1:
  2823                              <1> 	     ; / move arguments to bottom of users core
  2824                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2825                              <1> 		; cmp r2,(sp) / is r2 = beginning of argument
  2826                              <1> 			    ; / ptr list
  2827                              <1> 		; blo 1f / branch to 1f when all arguments
  2828                              <1> 		       ; / are moved
  2829                              <1> 		; mov -(r2),r3 / (r3) last non zero argument ptr
  2830                              <1> 	; 2:
  2831                              <1> 		; tstb (r3)+
  2832                              <1> 		; bne 2b / scan argument for \0 (nul)
  2833                              <1> 
  2834                              <1> 	; 2:
  2835                              <1> 		; movb -(r3),-(r5) / move argument char 
  2836                              <1> 				 ; / by char starting at "ecore"
  2837                              <1> 		; cmp r3,(r2) / moved all characters in 
  2838                              <1> 			    ; / this argument
  2839                              <1> 		; bhi 2b / branch 2b if not
  2840                              <1> 		; mov r5,(r4)+ / move r5 into top of users core;
  2841                              <1> 			     ; / r5 has pointer to nth arg
  2842                              <1> 		; br 1b / string
  2843                              <1> 	; 1:
  2844                              <1> 		; clrb -(r5)
  2845                              <1> 		; bic $1,r5 / make r5 even, r5 points to 
  2846                              <1> 			; / last word of argument strings
  2847                              <1> 		; mov $core,r2
  2848                              <1> 	
  2849                              <1> 	; 1: / move argument pointers into core following 
  2850                              <1> 	      ; / argument strings
  2851                              <1> 		; cmp r2,r4
  2852                              <1> 		; bhis 1f / branch to 1f when all pointers
  2853                              <1> 			; / are moved
  2854                              <1> 		; mov (r2)+,-(r5)
  2855                              <1> 		; br 1b
  2856                              <1> 	; 1:
  2857                              <1> 		; sub $core,r4 / gives number of arguments *2
  2858                              <1> 		; asr r4 / divide r4 by 2 to calculate 
  2859                              <1> 		       ; / the number of args stored
  2860                              <1> 		; mov r4,-(r5) / save number of arguments ahead
  2861                              <1> 			     ; / of the argument pointers
  2862                              <1> sysexec_13:
  2863                              <1> 	; 19/10/2015
  2864                              <1> 	; 18/10/2015
  2865                              <1> 	; 29/07/2015
  2866                              <1> 	; 25/07/2015
  2867                              <1> 	; 24/07/2015
  2868                              <1> 	; 20/07/2015
  2869                              <1> 	; 25/06/2015
  2870                              <1> 	; 24/06/2015
  2871                              <1> 	; 23/06/2015
  2872                              <1> 	;
  2873                              <1> 	; moving arguments to [ecore] is OK here..
  2874                              <1> 	; 18/10/2015
  2875 000046BA 89EC                <1> 	mov 	esp, ebp ; (**) restore kernel stack pointer
  2876                              <1> 	; ebx = beginning addres of argument list pointers
  2877                              <1> 	;	in user's stack
  2878                              <1> 	; 19/10/2015
  2879 000046BC 2B1D[0C6F0000]      <1> 	sub 	ebx, [ecore]
  2880 000046C2 81C300F0BFFF        <1> 	add     ebx, (ECORE - PAGE_SIZE)
  2881                              <1> 			; end of core - 4096 (last page)
  2882                              <1> 			; (virtual address)
  2883 000046C8 891D[186F0000]      <1> 	mov	[argv], ebx
  2884 000046CE 891D[C46E0000]      <1> 	mov	[u.break], ebx ; available user memory
  2885                              <1> 	;
  2886 000046D4 29C0                <1> 	sub	eax, eax
  2887 000046D6 C705[BC6E0000]2000- <1> 	mov	dword [u.count], 32 ; Executable file header size
  2887 000046DE 0000                <1>
  2888                              <1> 		; mov $14,u.count
  2889 000046E0 C705[A86E0000]-     <1> 	mov	dword [u.fofp], u.off
  2889 000046E6 [B46E0000]          <1>
  2890                              <1> 		; mov $u.off,u.fofp
  2891 000046EA A3[B46E0000]        <1> 	mov	[u.off], eax ; 0
  2892                              <1> 		; clr u.off / set offset in file to be read to zero
  2893                              <1> 	; 25/07/2015
  2894 000046EF A3[B86E0000]        <1> 	mov	[u.base], eax ; 0, start of user's core (virtual)
  2895                              <1> 	; 25/06/2015 
  2896 000046F4 66A1[7C6E0000]      <1> 	mov	ax, [ii]
  2897                              <1> 	; AX = i-number of the executable file
  2898 000046FA E86F0C0000          <1> 	call	readi
  2899                              <1> 		; jsr r0,readi / read in first six words of 
  2900                              <1> 			; / user's file, starting at $core
  2901                              <1> 		; mov sp,r5 / put users stack address in r5
  2902                              <1> 		; sub $core+40.,r5 / subtract $core +40, 
  2903                              <1> 				; / from r5 (leaves number of words
  2904                              <1> 				; / less 26 available for
  2905                              <1> 			     	; / program in user core
  2906                              <1> 		; mov r5,u.count /
  2907                              <1> 	; 25/06/2015
  2908 000046FF 8B0D[C46E0000]      <1> 	mov	ecx, [u.break] ; top of user's stack (physical addr.)
  2909 00004705 890D[BC6E0000]      <1> 	mov	[u.count], ecx ; save for overrun check
  2910                              <1> 	;
  2911 0000470B 8B0D[C06E0000]      <1> 	mov	ecx, [u.nread]
  2912 00004711 890D[C46E0000]      <1> 	mov	[u.break], ecx ; virtual address (offset from start)
  2913 00004717 80F920              <1> 	cmp	cl, 32
  2914 0000471A 7540                <1>         jne     short sysexec_15
  2915                              <1> 	;:
  2916                              <1> 	; 25/06/2015
  2917                              <1> 	; Retro UNIX 386 v1 (32 bit) executable file header format
  2918                              <1> 	; 18/10/2015
  2919 0000471C 8B35[086F0000]      <1> 	mov	esi, [pcore] ; start address of user's core memory 
  2920                              <1> 		             ; (phys. start addr. of the exec. file)
  2921 00004722 AD                  <1> 	lodsd
  2922 00004723 663DEB1E            <1> 	cmp	ax, 1EEBh ; EBH, 1Eh -> jump to +32
  2923 00004727 7533                <1> 	jne	short sysexec_15
  2924                              <1> 		; cmp core,$405 / br .+14 is first instruction 
  2925                              <1> 			      ; / if file is standard a.out format
  2926                              <1> 		; bne 1f / branch, if not standard format
  2927 00004729 AD                  <1> 	lodsd
  2928 0000472A 89C1                <1> 	mov	ecx, eax ; text (code) section size
  2929 0000472C AD                  <1> 	lodsd
  2930 0000472D 01C1                <1> 	add	ecx, eax ; + data section size (initialized data)
  2931                              <1> 		; mov core+2,r5 / put 2nd word of users program in r5;
  2932                              <1> 		              ; / number of bytes in program text	
  2933                              <1> 		; sub $14,r5 / subtract 12
  2934 0000472F 89CB                <1> 	mov	ebx, ecx
  2935                              <1> 	;
  2936                              <1> 	; 25/06/2015
  2937                              <1> 	; NOTE: These are for next versions of Retro UNIX 386
  2938                              <1> 	;	and SINGLIX operating systems (as code template).
  2939                              <1> 	;	Current Retro UNIX 386 v1 files can be max. 64KB
  2940                              <1> 	;	due to RUFS (floppy disk file system) restriction...
  2941                              <1> 	;	Overrun is not possible for current version. 	
  2942                              <1> 	;
  2943 00004731 AD                  <1> 	lodsd	
  2944 00004732 01C3                <1> 	add	ebx, eax ; + bss section size (for overrun checking)
  2945 00004734 3B1D[BC6E0000]      <1> 	cmp	ebx, [u.count]
  2946 0000473A 7711                <1> 	ja	short sysexec_14  ; program overruns stack !
  2947                              <1> 	;
  2948                              <1> 	; 24/07/2015
  2949                              <1> 	; add bss section size to [u.break]
  2950 0000473C 0105[C46E0000]      <1> 	add 	[u.break], eax
  2951                              <1> 	;
  2952 00004742 83E920              <1> 	sub	ecx, 32  ; header size (already loaded)
  2953                              <1> 	;cmp	ecx, [u.count]
  2954                              <1> 	;jnb	short sysexec_16
  2955                              <1> 		; cmp r5,u.count /
  2956                              <1> 		; bgt 1f / branch if r5 greater than u.count
  2957 00004745 890D[BC6E0000]      <1> 	mov	[u.count], ecx ; required read count
  2958                              <1> 		; mov r5,u.count
  2959                              <1> 	;
  2960 0000474B EB2A                <1> 	jmp	short sysexec_16
  2961                              <1> 	;
  2962                              <1> sysexec_14:
  2963                              <1> 	; 23/06/2015
  2964                              <1> 	; insufficient (out of) memory
  2965 0000474D C705[ED6E0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; 1
  2965 00004755 0000                <1>
  2966 00004757 E976F3FFFF          <1> 	jmp	error
  2967                              <1> 	;
  2968                              <1> sysexec_15:
  2969                              <1> 	; 25/06/2015
  2970 0000475C 0FB715[9C6B0000]    <1>         movzx   edx, word [i.size] ; file size
  2971 00004763 29CA                <1> 	sub	edx, ecx ; file size - loaded bytes
  2972 00004765 7627                <1> 	jna	short sysexec_17 ; no need to next read
  2973 00004767 01D1                <1> 	add	ecx, edx ; [i.size]
  2974 00004769 3B0D[BC6E0000]      <1> 	cmp	ecx, [u.count] ; overrun check (!)
  2975 0000476F 77DC                <1> 	ja	short sysexec_14
  2976 00004771 8915[BC6E0000]      <1> 	mov	[u.count], edx
  2977                              <1> sysexec_16:
  2978 00004777 66A1[7C6E0000]      <1> 	mov	ax, [ii] ; i-number
  2979 0000477D E8EC0B0000          <1> 	call	readi
  2980                              <1> 		; add core+10,u.nread / add size of user data area 
  2981                              <1> 		                    ; / to u.nread
  2982                              <1> 		; br 2f
  2983                              <1> 	; 1:
  2984                              <1> 		; jsr r0,readi / read in rest of file
  2985                              <1> 	; 2:
  2986 00004782 8B0D[C06E0000]      <1> 	mov	ecx, [u.nread]
  2987 00004788 010D[C46E0000]      <1> 	add	[u.break], ecx
  2988                              <1> 		; mov u.nread,u.break / set users program break to end of 
  2989                              <1> 				    ; / user code
  2990                              <1> 		; add $core+14,u.break / plus data area
  2991                              <1> sysexec_17: ; 20/07/2015
  2992                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2993                              <1> 	; ('iclose' is not needed for regular files, from now on)
  2994                              <1> 	;;mov	ax, [ii] ; i-number
  2995                              <1> 	;call	iclose
  2996                              <1> 	;	; jsr r0,iclose / does nothing
  2997 0000478E 31C0                <1>         xor     eax, eax
  2998 00004790 FEC0                <1> 	inc	al
  2999 00004792 66A3[DC6E0000]      <1> 	mov	[u.intr], ax ; 1 (interrupt/time-out is enabled)
  3000 00004798 66A3[DE6E0000]      <1> 	mov	[u.quit], ax ; 1 ('crtl+brk' signal is enabled) 
  3001                              <1> 	; 02/07/2015
  3002 0000479E 833D[F56E0000]00    <1>         cmp	dword [u.ppgdir], 0  ; is the caller sys_init (kernel) ?
  3003 000047A5 770C                <1> 	ja	short sysexec_18 ; no, the caller is user process
  3004                              <1> 	; If the caller is kernel (sys_init), 'sysexec' will come here
  3005 000047A7 8B15[D86A0000]      <1> 	mov	edx, [k_page_dir] ; kernel's page directory
  3006 000047AD 8915[F56E0000]      <1> 	mov	[u.ppgdir], edx ; next time 'sysexec' must not come here 
  3007                              <1> sysexec_18:
  3008                              <1> 	; 18/10/2015
  3009                              <1> 	; 05/08/2015
  3010                              <1> 	; 29/07/2015
  3011 000047B3 8B2D[186F0000]      <1> 	mov	ebp, [argv] ; user's stack pointer must point to argument
  3012                              <1> 			    ; list pointers (argument count)
  3013 000047B9 FA                  <1> 	cli
  3014 000047BA 8B25[746A0000]      <1>         mov     esp, [tss.esp0]  ; ring 0 (kernel) stack pointer
  3015                              <1> 	;mov   	esp, [u.sp] ; Restore Kernel stack
  3016                              <1> 			    ; for this process	 
  3017                              <1> 	;add	esp, 20 ; --> EIP, CS, EFLAGS, ESP, SS
  3018                              <1> 	;xor	eax, eax ; 0
  3019 000047C0 FEC8                <1> 	dec	al ; eax = 0
  3020 000047C2 66BA2300            <1> 	mov	dx, UDATA
  3021 000047C6 6652                <1> 	push	dx  ; user's stack segment
  3022 000047C8 55                  <1> 	push	ebp ; user's stack pointer
  3023                              <1> 		    ; (points to number of arguments)
  3024 000047C9 FB                  <1> 	sti
  3025 000047CA 9C                  <1> 	pushfd	; EFLAGS
  3026                              <1> 		; Set IF for enabling interrupts in user mode	
  3027                              <1> 	;or	dword [esp], 200h 
  3028                              <1> 	;
  3029                              <1> 	;mov	bx, UCODE
  3030                              <1> 	;push	bx ; user's code segment
  3031 000047CB 6A1B                <1> 	push	UCODE
  3032                              <1> 	;push	0
  3033 000047CD 50                  <1> 	push	eax ; EIP (=0) - start address -	
  3034                              <1> 		; clr -(r5) / popped into ps when rti in 
  3035                              <1> 			  ; / sysrele is executed
  3036                              <1> 		; mov $core,-(r5) / popped into pc when rti 
  3037                              <1> 		                ; / in sysrele is executed
  3038                              <1> 		;mov r5,0f / load second copyz argument
  3039                              <1> 		;tst -(r5) / decrement r5
  3040 000047CE 8925[906E0000]      <1> 	mov	[u.sp], esp ; 29/07/2015
  3041                              <1> 	; 05/08/2015
  3042                              <1> 	; Remedy of a General Protection Fault during 'iretd' is here !
  3043                              <1> 	; ('push dx' would cause to general protection fault, 
  3044                              <1> 	; after 'pop ds' etc.)
  3045                              <1> 	;
  3046                              <1> 	;; push dx ; ds (UDATA)
  3047                              <1> 	;; push dx ; es (UDATA)
  3048                              <1> 	;; push dx ; fs (UDATA)
  3049                              <1> 	;; push dx ; gs (UDATA)
  3050                              <1> 	;
  3051                              <1> 	; This is a trick to prevent general protection fault
  3052                              <1> 	; during 'iretd' intruction at the end of 'sysrele' (in u1.s):
  3053 000047D4 8EC2                <1> 	mov 	es, dx ; UDATA
  3054 000047D6 06                  <1> 	push 	es ; ds (UDATA)
  3055 000047D7 06                  <1> 	push 	es ; es (UDATA)
  3056 000047D8 06                  <1> 	push 	es ; fs (UDATA)
  3057 000047D9 06                  <1> 	push	es ; gs (UDATA)
  3058 000047DA 66BA1000            <1> 	mov	dx, KDATA
  3059 000047DE 8EC2                <1> 	mov	es, dx
  3060                              <1> 	;
  3061                              <1> 	;; pushad simulation
  3062 000047E0 89E5                <1> 	mov	ebp, esp ; esp before pushad
  3063 000047E2 50                  <1> 	push	eax ; eax (0)
  3064 000047E3 50                  <1> 	push	eax ; ecx (0)
  3065 000047E4 50                  <1> 	push	eax ; edx (0)
  3066 000047E5 50                  <1> 	push	eax ; ebx (0)
  3067 000047E6 55                  <1> 	push	ebp ; esp before pushad
  3068 000047E7 50                  <1> 	push	eax ; ebp (0)
  3069 000047E8 50                  <1> 	push	eax ; esi (0)		
  3070 000047E9 50                  <1> 	push	eax ; edi (0)	
  3071                              <1> 	;
  3072 000047EA A3[986E0000]        <1> 	mov	[u.r0], eax ; eax = 0
  3073 000047EF 8925[946E0000]      <1> 	mov	[u.usp], esp
  3074                              <1> 		; mov r5,u.r0 /
  3075                              <1> 		; sub $16.,r5 / skip 8 words
  3076                              <1> 		; mov r5,u.sp / assign user stack pointer value, 
  3077                              <1> 		;             / effectively zeroes all regs
  3078                              <1> 			    ; / when sysrele is executed
  3079                              <1> 		; jsr r0,copyz; core; 0:0 / zero user's core
  3080                              <1> 		; clr u.break
  3081                              <1> 		; mov r5,sp / point sp to user's stack
  3082                              <1> 	;
  3083 000047F5 E9FAF2FFFF          <1> 	jmp	sysret0
  3084                              <1> 	;jmp	sysret
  3085                              <1> 		; br sysret3 / return to core image at $core
  3086                              <1> 
  3087                              <1> get_argp:
  3088                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3089                              <1> 	; 18/10/2015 (nbase, ncount)
  3090                              <1> 	; 21/07/2015
  3091                              <1> 	; 24/06/2015 (Retro UNIX 386 v1)
  3092                              <1> 	; Get (virtual) address of argument from user's core memory
  3093                              <1> 	;
  3094                              <1> 	; INPUT:
  3095                              <1> 	;	esi = virtual address of argument pointer
  3096                              <1> 	; OUTPUT:
  3097                              <1> 	;	eax = virtual address of argument
  3098                              <1> 	;
  3099                              <1> 	; Modified registers: EAX, EBX, ECX, EDX, ESI 
  3100                              <1> 	;
  3101 000047FA 833D[F56E0000]00    <1>  	cmp     dword [u.ppgdir], 0 ; /etc/init ?
  3102                              <1> 				    ; (the caller is kernel)
  3103                              <1> 	;jna	short get_argpk 
  3104                              <1> 	; 24/12/2021
  3105 00004801 7719                <1> 	ja	short get_argp5
  3106                              <1> get_argpk:
  3107                              <1> 	; Argument is in kernel's memory space
  3108 00004803 66C705[146F0000]00- <1> 	mov	word [ncount], PAGE_SIZE ; 4096
  3108 0000480B 10                  <1>
  3109 0000480C 8935[106F0000]      <1> 	mov	[nbase], esi
  3110 00004812 8305[106F0000]04    <1> 	add	dword [nbase], 4
  3111 00004819 8B06                <1> 	mov	eax, [esi] ; virtual addr. = physcal addr.
  3112 0000481B C3                  <1> 	retn
  3113                              <1> get_argp5:
  3114 0000481C 89F3                <1>      	mov	ebx, esi
  3115 0000481E E87FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3116 00004823 7257                <1>         jc      short get_argp_err ; 24/12/2021 (short jump)
  3117 00004825 A3[106F0000]        <1> 	mov 	[nbase], eax ; physical address	
  3118 0000482A 66890D[146F0000]    <1> 	mov	[ncount], cx ; remain byte count in page (1-4096)
  3119 00004831 B804000000          <1> 	mov	eax, 4 ; 21/07/2015
  3120                              <1> 	;cmp	cx, ax ; 4
  3121 00004836 39C1                <1> 	cmp	ecx, eax ; 24/12/2021
  3122 00004838 734C                <1> 	jnb	short get_argp2
  3123 0000483A 89F3                <1> 	mov	ebx, esi
  3124 0000483C 01CB                <1> 	add	ebx, ecx
  3125 0000483E E85FE9FFFF          <1> 	call	get_physical_addr ; get physical address
  3126 00004843 7237                <1> 	jc	short get_argp_err
  3127                              <1> 	;push	esi
  3128 00004845 89C6                <1> 	mov	esi, eax
  3129 00004847 66870D[146F0000]    <1> 	xchg	cx, [ncount]
  3130 0000484E 8735[106F0000]      <1> 	xchg	esi, [nbase]
  3131 00004854 B504                <1> 	mov	ch, 4
  3132 00004856 28CD                <1> 	sub	ch, cl
  3133                              <1> get_argp0:
  3134 00004858 AC                  <1> 	lodsb
  3135                              <1> 	;push	ax
  3136                              <1> 	; 24/12/2021
  3137 00004859 50                  <1> 	push	eax
  3138 0000485A FEC9                <1> 	dec	cl
  3139 0000485C 75FA                <1>         jnz     short get_argp0
  3140 0000485E 8B35[106F0000]      <1> 	mov	esi, [nbase]
  3141                              <1> 	; 21/07/2015
  3142 00004864 0FB6C5              <1> 	movzx	eax, ch
  3143 00004867 0105[106F0000]      <1> 	add	[nbase], eax
  3144 0000486D 662905[146F0000]    <1> 	sub	[ncount], ax
  3145                              <1> get_argp1:
  3146 00004874 AC                  <1> 	lodsb
  3147 00004875 FECD                <1> 	dec	ch
  3148 00004877 7423                <1>         jz      short get_argp3
  3149                              <1> 	;push	ax
  3150                              <1> 	; 24/12/2021
  3151 00004879 50                  <1> 	push	eax
  3152 0000487A EBF8                <1> 	jmp     short get_argp1
  3153                              <1> 	; 24/12/2021
  3154                              <1> get_argp_err:
  3155 0000487C A3[ED6E0000]        <1> 	mov	[u.error], eax
  3156 00004881 E94CF2FFFF          <1> 	jmp	error
  3157                              <1> get_argp2:
  3158                              <1> 	; 21/07/2015
  3159                              <1> 	;mov	eax, 4
  3160 00004886 8B15[106F0000]      <1> 	mov 	edx, [nbase] ; 18/10/2015
  3161 0000488C 0105[106F0000]      <1> 	add	[nbase], eax
  3162 00004892 662905[146F0000]    <1> 	sub	[ncount], ax
  3163                              <1> 	;
  3164 00004899 8B02                <1> 	mov	eax, [edx]
  3165 0000489B C3                  <1> 	retn
  3166                              <1> get_argp3:
  3167 0000489C B103                <1> 	mov	cl, 3
  3168                              <1> get_argp4:
  3169 0000489E C1E008              <1> 	shl	eax, 8
  3170                              <1> 	;pop	dx
  3171                              <1> 	; 24/12/2021
  3172 000048A1 5A                  <1> 	pop	edx
  3173 000048A2 88D0                <1> 	mov 	al, dl
  3174 000048A4 E2F8                <1>         loop    get_argp4
  3175                              <1> 	;pop	esi
  3176 000048A6 C3                  <1> 	retn	
  3177                              <1> 
  3178                              <1> sysfstat:
  3179                              <1> 	; 03/02/2022
  3180                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3181                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3182                              <1> 	;
  3183                              <1> 	; 'sysfstat' is identical to 'sysstat' except that it operates
  3184                              <1> 	; on open files instead of files given by name. It puts the
  3185                              <1> 	; buffer address on the stack, gets the i-number and
  3186                              <1> 	; checks to see if the file is open for reading or writing.
  3187                              <1> 	; If the file is open for writing (i-number is negative)
  3188                              <1> 	; the i-number is set positive and a branch into 'sysstat'
  3189                              <1> 	; is made.	
  3190                              <1> 	;
  3191                              <1> 	; Calling sequence:
  3192                              <1> 	;	sysfstat; buf
  3193                              <1> 	; Arguments:
  3194                              <1> 	;	buf - buffer address
  3195                              <1> 	;
  3196                              <1> 	; Inputs: *u.r0 - file descriptor
  3197                              <1> 	; Outputs: buffer is loaded with file information
  3198                              <1> 	; ...............................................................
  3199                              <1> 	;				
  3200                              <1> 	; Retro UNIX 8086 v1 modification:
  3201                              <1> 	;       'sysfstat' system call has two arguments; so,
  3202                              <1> 	;	* 1st argument, file descriptor is in BX register
  3203                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3204                              <1> 
  3205                              <1> 	; / set status of open file
  3206                              <1> 		; jsr r0,arg; u.off / put buffer address in u.off
  3207 000048A7 51                  <1> 	push	ecx
  3208                              <1> 		; mov u.off,-(sp) / put buffer address on the stack
  3209                              <1> 		; mov *u.r0,r1 / put file descriptor in r1
  3210                              <1> 		; jsr r0,getf / get the files i-number
  3211                              <1> 	; BX = file descriptor (file number)
  3212 000048A8 E8F2000000          <1> 	call	getf1
  3213                              <1> 	; 03/02/2022
  3214 000048AD 21C0                <1> 	and	eax, eax
  3215                              <1> 	;and	ax, ax ; i-number of the file
  3216                              <1> 		; tst	r1 / is it 0?
  3217                              <1> 	;jz	error
  3218                              <1> 		; beq error3 / yes, error
  3219 000048AF 750F                <1> 	jnz	short sysfstat1
  3220 000048B1 C705[ED6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  3220 000048B9 0000                <1>
  3221 000048BB E912F2FFFF          <1> 	jmp	error
  3222                              <1> sysfstat1:
  3223 000048C0 80FC80              <1> 	cmp	ah, 80h
  3224 000048C3 7222                <1>         jb      short sysstat1
  3225                              <1> 		; bgt 1f / if i-number is negative (open for writing)
  3226 000048C5 66F7D8              <1> 	neg	ax
  3227                              <1> 		; neg r1 / make it positive, then branch
  3228 000048C8 EB1D                <1> 	jmp	short sysstat1
  3229                              <1> 		; br 1f / to 1f
  3230                              <1> sysstat:
  3231                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3232                              <1> 	; 18/10/2015
  3233                              <1> 	; 07/10/2015
  3234                              <1> 	; 02/09/2015
  3235                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3236                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3237                              <1> 	;
  3238                              <1> 	; 'sysstat' gets the status of a file. Its arguments are the
  3239                              <1> 	; name of the file and buffer address. The buffer is 34 bytes
  3240                              <1> 	; long and information about the file placed in it.	
  3241                              <1> 	; sysstat calls 'namei' to get the i-number of the file.
  3242                              <1> 	; Then 'iget' is called to get i-node in core. The buffer
  3243                              <1> 	; is then loaded and the results are given in the UNIX
  3244                              <1> 	; Programmers Manual sysstat (II).	
  3245                              <1> 	;
  3246                              <1> 	; Calling sequence:
  3247                              <1> 	;	sysstat; name; buf
  3248                              <1> 	; Arguments:
  3249                              <1> 	;	name - points to the name of the file
  3250                              <1> 	;	buf - address of a 34 bytes buffer
  3251                              <1> 	; Inputs: -
  3252                              <1> 	; Outputs: buffer is loaded with file information
  3253                              <1> 	; ...............................................................
  3254                              <1> 	;				
  3255                              <1> 	; Retro UNIX 8086 v1 modification: 
  3256                              <1> 	;       'sysstat' system call has two arguments; so,
  3257                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  3258                              <1> 	;	to get sysstat system call arguments from the user;
  3259                              <1> 	;	* 1st argument, name is pointed to by BX register
  3260                              <1> 	;	* 2nd argument, buf is pointed to by CX register
  3261                              <1> 	;
  3262                              <1> 	;	NOTE: Retro UNIX 8086 v1 'arg2' routine gets these
  3263                              <1> 	;	      arguments which were in these registers;
  3264                              <1> 	;	      but, it returns by putting the 1st argument
  3265                              <1> 	;	      in 'u.namep' and the 2nd argument
  3266                              <1> 	;	      on top of stack. (1st argument is offset of the
  3267                              <1> 	;	      file/path name in the user's program segment.)		 	
  3268                              <1> 	
  3269                              <1> 	; / ; name of file; buffer - get files status
  3270                              <1> 		; jsr r0,arg2 / get the 2 arguments
  3271 000048CA 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  3272 000048D0 51                  <1> 	push	ecx
  3273 000048D1 E8FA000000          <1> 	call	namei
  3274                              <1> 		; jsr r0,namei / get the i-number for the file
  3275                              <1> 	;jc	error
  3276                              <1> 		; br error3 / no such file, error
  3277 000048D6 730F                <1> 	jnc	short sysstat1
  3278                              <1> 	; pop 	ecx
  3279                              <1> sysstat_err0:
  3280                              <1> 	; 'file not found !' error
  3281 000048D8 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  3281 000048E0 0000                <1>
  3282 000048E2 E9EBF1FFFF          <1> 	jmp	error
  3283                              <1> 
  3284                              <1> ;statx: db 0
  3285                              <1> 
  3286                              <1> sysstat1: ; 1:
  3287 000048E7 E8AE080000          <1> 	call	iget
  3288                              <1> 		; jsr r0,iget / get the i-node into core
  3289                              <1> 	; 07/10/2015 (ax = [ii], inode number)
  3290                              <1> 	; 02/09/2015
  3291 000048EC 8F05[B86E0000]      <1> 	pop	dword [u.base]
  3292                              <1> 		; mov (sp)+,r3 / move u.off to r3 (points to buffer)
  3293 000048F2 E855000000          <1> 	call	sysstat_gpa ; get physical address
  3294 000048F7 730A                <1> 	jnc 	short sysstat2
  3295                              <1> sysstat_err1:
  3296 000048F9 A3[ED6E0000]        <1> 	mov	dword [u.error], eax ; error code
  3297 000048FE E9CFF1FFFF          <1> 	jmp	error
  3298                              <1> sysstat2:
  3299 00004903 A0[7C6E0000]        <1> 	mov 	al, [ii] ; 07/10/2015 (result of 'iget' call, above)
  3300 00004908 AA                  <1> 	stosb
  3301 00004909 FF05[B86E0000]      <1> 	inc 	dword [u.base]
  3302                              <1> 	;dec 	cx
  3303                              <1> 	; 24/12/2021
  3304 0000490F 49                  <1> 	dec	ecx
  3305 00004910 7505                <1> 	jnz	short sysstat3
  3306 00004912 E835000000          <1> 	call	sysstat_gpa
  3307                              <1> 	;jc	short sysstat_err1
  3308                              <1> sysstat3:
  3309 00004917 A0[7D6E0000]        <1> 	mov 	al, [ii+1] ; 07/10/2015 (result of 'iget' call, above)
  3310 0000491C AA                  <1> 	stosb
  3311                              <1> 		; mov r1,(r3)+ / put i-number in 1st word of buffer
  3312 0000491D FF05[B86E0000]      <1> 	inc 	dword [u.base]
  3313                              <1> 	;;dec 	word [u.pcount]
  3314                              <1> 	;dec	cx
  3315 00004923 49                  <1> 	dec	ecx ; 24/12/2021
  3316 00004924 7505                <1> 	jnz	short sysstat4
  3317 00004926 E821000000          <1> 	call	sysstat_gpa
  3318                              <1> 	;jc	short sysstat_err1	
  3319                              <1> sysstat4:
  3320 0000492B BE[986B0000]        <1> 	mov	esi, inode
  3321                              <1> 		; mov $inode,r2 / r2 points to i-node
  3322                              <1> sysstat5: ; 1:
  3323 00004930 A4                  <1> 	movsb
  3324                              <1> 		; mov (r2)+,(r3)+ / move rest of i-node to buffer
  3325 00004931 FF05[B86E0000]      <1> 	inc 	dword [u.base]
  3326                              <1> 	;;dec 	word [u.pcount]
  3327                              <1> 	;dec 	cx
  3328                              <1> 	; 24/12/2021
  3329 00004937 49                  <1> 	dec	ecx
  3330 00004938 7505                <1> 	jnz	short sysstat6
  3331 0000493A E80D000000          <1> 	call	sysstat_gpa
  3332                              <1> 	;jc	short sysstat_err1
  3333                              <1> sysstat6:		
  3334 0000493F 81FE[B86B0000]      <1> 	cmp	esi, inode + 32
  3335                              <1> 		; cmp r2,$inode+32 / done?
  3336 00004945 75E9                <1> 	jne	short sysstat5
  3337                              <1> 		; bne 1b / no, go back
  3338 00004947 E9A6F1FFFF          <1> 	jmp	sysret
  3339                              <1> 		; br sysret3 / return through sysret
  3340                              <1> 	;
  3341                              <1> sysstat_gpa: ; get physical address of file status buffer
  3342                              <1> 	; 02/09/2015
  3343 0000494C 8B1D[B86E0000]      <1> 	mov 	ebx, [u.base]
  3344                              <1> 	; 07/10/2015
  3345 00004952 E84BE8FFFF          <1> 	call	get_physical_addr ; get physical address
  3346                              <1> 	;jc	short sysstat_gpa1
  3347 00004957 72A0                <1> 	jc	short sysstat_err1
  3348                              <1> 	; 18/10/2015
  3349 00004959 89C7                <1> 	mov	edi, eax ; physical address
  3350                              <1> 	;mov	[u.pcount], cx ; remain bytes in page
  3351                              <1> ;sysstat_gpa1:
  3352 0000495B C3                  <1> 	retn
  3353                              <1> 
  3354                              <1> fclose:
  3355                              <1> 	; 08/01/2022
  3356                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3357                              <1> 	; 18/06/2015 (Retro UNIX 386 v1 - Beginning)
  3358                              <1> 	;            (32 bit offset pointer modification)
  3359                              <1> 	; 19/04/2013 - 12/01/2014 (Retro UNIX 8086 v1)
  3360                              <1> 	;
  3361                              <1> 	; Given the file descriptor (index to the u.fp list)
  3362                              <1> 	; 'fclose' first gets the i-number of the file via 'getf'.
  3363                              <1> 	; If i-node is active (i-number > 0) the entry in 
  3364                              <1> 	; u.fp list is cleared. If all the processes that opened
  3365                              <1> 	; that file close it, then fsp etry is freed and the file
  3366                              <1> 	; is closed. If not a return is taken. 
  3367                              <1> 	; If the file has been deleted while open, 'anyi' is called
  3368                              <1> 	; to see anyone else has it open, i.e., see if it is appears
  3369                              <1> 	; in another entry in the fsp table. Upon return from 'anyi'
  3370                              <1> 	; a check is made to see if the file is special.	
  3371                              <1> 	;
  3372                              <1> 	; INPUTS ->
  3373                              <1> 	;    r1 - contains the file descriptor (value=0,1,2...)
  3374                              <1> 	;    u.fp - list of entries in the fsp table
  3375                              <1> 	;    fsp - table of entries (4 words/entry) of open files.	 
  3376                              <1> 	; OUTPUTS ->
  3377                              <1> 	;    r1 - contains the same file descriptor
  3378                              <1> 	;    r2 - contains i-number
  3379                              <1> 	;
  3380                              <1> 	; ((AX = R1))
  3381                              <1> 	; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))
  3382                              <1> 	;
  3383                              <1> 	; Retro UNIX 8086 v1 modification : CF = 1
  3384                              <1> 	;              if i-number of the file is 0. (error)  	
  3385                              <1> 
  3386                              <1> 	;movzx	edx, ax ; **
  3387                              <1> 	; 24/12/2021
  3388                              <1> 	;movzx	edx, al
  3389 0000495C 89C2                <1> 	mov	edx, eax ; eax <= 10 ; 24/12/2021
  3390 0000495E 50                  <1> 	push	eax ; ***
  3391                              <1> 	;push	ax ; ***
  3392                              <1> 		; mov r1,-(sp) / put r1 on the stack (it contains 
  3393                              <1> 			     ; / the index to u.fp list)
  3394 0000495F E839000000          <1> 	call	getf
  3395                              <1> 		; jsr r0,getf / r1 contains i-number, 
  3396                              <1> 			    ; / cdev has device =, u.fofp 
  3397                              <1> 			    ; / points to 3rd word of fsp entry
  3398 00004964 6683F801            <1> 	cmp	ax, 1 ; r1
  3399                              <1> 		; tst r1 / is i-number 0?
  3400 00004968 7231                <1> 	jb	short fclose_2
  3401                              <1> 		; beq 1f / yes, i-node not active so return
  3402                              <1> 		; tst (r0)+ / no, jump over error return
  3403 0000496A 89D3                <1> 	mov	ebx, edx ; **
  3404                              <1> 	; 24/12/2021
  3405 0000496C 89C2                <1> 	mov	edx, eax ; *
  3406                              <1> 	;mov 	dx, ax ; *
  3407                              <1> 		; mov r1,r2 / move i-number to r2 ;*
  3408                              <1> 		; mov (sp),r1 / restore value of r1 from the stack
  3409                              <1> 			    ; / which is index to u.fp ; **
  3410 0000496E C683[9E6E0000]00    <1> 	mov	byte [ebx+u.fp], 0
  3411                              <1> 		; clrb u.fp(r1) / clear that entry in the u.fp list
  3412 00004975 8B1D[A86E0000]      <1> 	mov	ebx, [u.fofp]
  3413                              <1> 		; mov u.fofp,r1 / r1 points to 3rd word in fsp entry
  3414                              <1> fclose_0:
  3415 0000497B FE4B04              <1> 	dec	byte [ebx+4] ; 18/06/2015
  3416                              <1> 		; decb 2(r1) / decrement the number of processes 
  3417                              <1> 			   ; / that have opened the file
  3418 0000497E 791B                <1> 	jns	short fclose_2 ; jump if not negative (jump if bit 7 is 0)	 
  3419                              <1> 		; bge 1f / if all processes haven't closed the file, return
  3420                              <1> 	;
  3421                              <1> 	; 24/12/2021
  3422 00004980 52                  <1> 	push	edx ; *
  3423                              <1> 	;push	dx ; *
  3424                              <1> 		; mov r2,-(sp) / put r2 on the stack (i-number)
  3425                              <1> 	;xor	ax, ax ; 0
  3426                              <1> 	; 24/12/2021
  3427 00004981 31C0                <1> 	xor	eax, eax
  3428 00004983 668943FC            <1> 	mov	[ebx-4], ax ; 0
  3429                              <1> 		; clr -4(r1) / clear 1st word of fsp entry
  3430 00004987 8A4305              <1> 	mov	al, [ebx+5] ; 18/06/2015
  3431                              <1> 		; tstb	3(r1) / has this file been deleted
  3432 0000498A 20C0                <1> 	and	al, al
  3433 0000498C 7407                <1> 	jz	short fclose_1
  3434                              <1> 		; beq 2f / no, branch
  3435                              <1> 	; 08/01/2022
  3436 0000498E 89D0                <1> 	mov	eax, edx
  3437                              <1> 	;mov	ax, dx ; *
  3438                              <1> 		; mov r2,r1 / yes, put i-number back into r1
  3439                              <1> 	; AX = inode number
  3440 00004990 E85A040000          <1> 	call	anyi
  3441                              <1> 		; jsr r0,anyi / free all blocks related to i-number
  3442                              <1> 			    ; / check if file appears in fsp again
  3443                              <1> fclose_1: ; 2:
  3444                              <1> 	; 24/12/2021
  3445 00004995 58                  <1> 	pop	eax ; * 
  3446                              <1> 	;pop	ax ; *
  3447                              <1> 		; mov (sp)+,r1 / put i-number back into r1
  3448 00004996 E8C2100000          <1> 	call	iclose ; close if it is special file 
  3449                              <1> 		; jsr r0,iclose / check to see if its a special file
  3450                              <1> fclose_2: ; 1:
  3451                              <1> 	; 24/12/2021
  3452 0000499B 58                  <1> 	pop	eax ; ***
  3453                              <1> 	;pop	ax ; ***
  3454                              <1> 		; mov (sp)+,r1 / put index to u.fp back into r1
  3455 0000499C C3                  <1> 	retn
  3456                              <1> 		; rts r0
  3457                              <1> 
  3458                              <1> 	; 09/01/2022
  3459                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1. - Kernel v0.2.1.2)
  3460                              <1> getf:	; / get the device number and the i-number of an open file
  3461                              <1> 	; 13/05/2015
  3462                              <1> 	; 11/05/2015 (Retro UNIX 386 v1 - Beginning)
  3463                              <1> 	; 19/04/2013 - 18/11/2013 (Retro UNIX 8086 v1)
  3464                              <1> 	;
  3465 0000499D 89C3                <1> 	mov	ebx, eax
  3466                              <1> getf1: ;; Calling point from 'rw1' (23/05/2013)
  3467                              <1> 	; 08/01/2022
  3468 0000499F 29C0                <1> 	sub	eax, eax
  3469                              <1> 	;
  3470 000049A1 83FB0A              <1> 	cmp	ebx, 10
  3471                              <1> 		; cmp r1,$10. / user limited to 10 open files
  3472 000049A4 7329                <1>         jnb	short getf2 ; 13/05/2015
  3473                              <1> 	;jnb	error
  3474                              <1> 		; bhis error3 / u.fp is table of users open files, 
  3475                              <1> 			    ; / index in fsp table
  3476                              <1> 	; 08/01/2022
  3477 000049A6 8A83[9E6E0000]      <1> 	mov	al, [ebx+u.fp]
  3478                              <1> 	;mov	bl, [ebx+u.fp]
  3479                              <1> 		; movb	u.fp(r1),r1 / r1 contains number of entry 
  3480                              <1> 		                  ; / in fsp table
  3481                              <1> 	; 08/01/2022
  3482 000049AC 08C0                <1> 	or	al, al
  3483 000049AE 741F                <1> 	jz	short getf2	
  3484                              <1> 	;or	bl, bl
  3485                              <1> 	;jnz	short getf3
  3486                              <1> 	;;jz	short getf4
  3487                              <1> 		; beq 1f / if its zero return
  3488                              <1> ;getf2:
  3489                              <1> ;	; 08/01/2022
  3490                              <1> ;	; 'File not open !' error (ax=0)
  3491                              <1> ;	;sub	eax, eax
  3492                              <1> ;	retn
  3493                              <1> 
  3494                              <1> getf3:	
  3495                              <1> 	; Retro UNIX 386 v1 modification ! (11/05/2015)
  3496                              <1> 	;
  3497                              <1> 	; 'fsp' table (10 bytes/entry)
  3498                              <1> 	; bit 15				   bit 0
  3499                              <1> 	; ---|-------------------------------------------
  3500                              <1> 	; r/w|		i-number of open file
  3501                              <1> 	; ---|-------------------------------------------
  3502                              <1> 	;		   device number
  3503                              <1> 	; -----------------------------------------------
  3504                              <1> 	; offset pointer, r/w pointer to file (bit 0-15)
  3505                              <1> 	; -----------------------------------------------
  3506                              <1> 	; offset pointer, r/w pointer to file (bit 16-31)
  3507                              <1> 	; ----------------------|------------------------
  3508                              <1> 	;  flag that says file 	| number of processes
  3509                              <1> 	;   has been deleted	| that have file open 
  3510                              <1> 	; ----------------------|------------------------
  3511                              <1> 	;
  3512                              <1> 	;mov	eax, 10
  3513                              <1> 	; 08/01/2022
  3514 000049B0 B30A                <1> 	mov	bl, 10
  3515 000049B2 F6E3                <1> 	mul	bl
  3516 000049B4 BB[626C0000]        <1> 	mov	ebx, fsp-6 ; the 3rd word in the fsp entry
  3517 000049B9 01C3                <1> 	add	ebx, eax
  3518                              <1> 		; asl r1
  3519                              <1> 		; asl r1 / multiply by 8 to get index into 
  3520                              <1> 		       ; / fsp table entry
  3521                              <1> 		; asl r1
  3522                              <1> 		; add $fsp-4,r1 / r1 is pointing at the 3rd word 
  3523                              <1> 			      ; / in the fsp entry
  3524 000049BB 891D[A86E0000]      <1> 	mov	[u.fofp], ebx
  3525                              <1> 		; mov r1,u.fofp / save address of 3rd word 
  3526                              <1> 			      ; / in fsp entry in u.fofp
  3527 000049C1 4B                  <1> 	dec	ebx
  3528 000049C2 4B                  <1> 	dec	ebx
  3529                              <1> 	;mov	ax, [ebx]
  3530                              <1> 	; 09/01/2022
  3531 000049C3 8A03                <1> 	mov	al, [ebx]
  3532 000049C5 A2[7F6E0000]        <1> 	mov	[cdev], al ; ;;Retro UNIX 8086 v1 ! 
  3533                              <1> 	;mov	[cdev], ax ; ;;in fact (!) 
  3534                              <1> 			     ;;dev number is in 1 byte
  3535                              <1> 		; mov -(r1),cdev / remove the device number cdev
  3536 000049CA 4B                  <1> 	dec	ebx
  3537 000049CB 4B                  <1> 	dec	ebx
  3538 000049CC 668B03              <1> 	mov	ax, [ebx]
  3539                              <1> 		; mov -(r1),r1 / and the i-number  r1
  3540                              <1> getf2:	; 08/01/2022
  3541                              <1> getf4:	; 1:
  3542 000049CF C3                  <1> 	retn
  3543                              <1> 		; rts r0
  3544                              <1> 
  3545                              <1> namei:
  3546                              <1> 	; 03/02/2022
  3547                              <1> 	; 09/01/2022
  3548                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  3549                              <1> 	; 04/12/2015 (Retro UNIX 386 v1.1, 14 byte file names)
  3550                              <1> 	; 18/10/2015 (nbase, ncount)
  3551                              <1> 	; 12/10/2015
  3552                              <1> 	; 21/08/2015
  3553                              <1> 	; 18/07/2015
  3554                              <1> 	; 02/07/2015
  3555                              <1> 	; 17/06/2015
  3556                              <1> 	; 16/06/2015 (Retro UNIX 386 v1 - Beginning)
  3557                              <1> 	; 24/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  3558                              <1> 	;
  3559                              <1> 	; 'namei' takes a file path name and returns i-number of
  3560                              <1> 	; the file in the current directory or the root directory
  3561                              <1> 	; (if the first character of the pathname is '/').	
  3562                              <1> 	;
  3563                              <1> 	; INPUTS ->
  3564                              <1> 	;    u.namep - points to a file path name
  3565                              <1> 	;    u.cdir - i-number of users directory
  3566                              <1> 	;    u.cdev - device number on which user directory resides	
  3567                              <1> 	; OUTPUTS ->
  3568                              <1> 	;    r1 - i-number of file
  3569                              <1> 	;    cdev
  3570                              <1> 	;    u.dirbuf - points to directory entry where a match 
  3571                              <1> 	;               occurs in the search for file path name.
  3572                              <1> 	;	        If no match u.dirb points to the end of 
  3573                              <1> 	;               the directory and r1 = i-number of the current
  3574                              <1> 	;	        directory.	
  3575                              <1> 	; ((AX = R1))
  3576                              <1> 	;
  3577                              <1> 	; (Retro UNIX Prototype : 07/10/2012 - 05/01/2013, UNIXCOPY.ASM)
  3578                              <1>         ; ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  3579                              <1> 	;
  3580                              <1> 
  3581 000049D0 66A1[9C6E0000]      <1> 	mov	ax, [u.cdir]
  3582                              <1> 		; mov u.cdir,r1 / put the i-number of current directory
  3583                              <1> 			      ; / in r1
  3584                              <1> 	; 09/01/2022
  3585 000049D6 8A15[E26E0000]      <1> 	mov	dl, [u.cdrv]
  3586 000049DC 8815[7F6E0000]      <1> 	mov	[cdev], dl
  3587                              <1> 	;mov	dx, [u.cdrv]
  3588                              <1> 	;mov	[cdev], dx 	    ; NOTE: Retro UNIX 8086 v1 
  3589                              <1> 				    ; device/drive number is in 1 byte, 
  3590                              <1> 				    ; not in 1 word!
  3591                              <1> 		; mov u.cdev,cdev / device number for users directory 
  3592                              <1> 				; / into cdev
  3593                              <1> 	; 12/10/2015
  3594                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3595                              <1>       	 ; convert virtual (pathname) addr to physical address
  3596 000049E2 E822010000          <1> 	call    trans_addr_nmbp ; 12/10/2015
  3597                              <1> 		; esi = physical address of [u.namep]
  3598                              <1> 		; ecx = byte count in the page
  3599 000049E7 803E2F              <1> 	cmp	byte [esi], '/'
  3600                              <1> 		; cmpb *u.namep,$'/ / is first char in file name a /
  3601 000049EA 751D                <1> 	jne	short namei_1
  3602                              <1> 		; bne 1f
  3603 000049EC FF05[B06E0000]      <1> 	inc	dword [u.namep]
  3604                              <1> 		; inc u.namep / go to next char
  3605                              <1> 	;dec	cx ; remain byte count in the page
  3606                              <1> 	; 24/12/2021
  3607 000049F2 49                  <1> 	dec	ecx
  3608 000049F3 7506                <1> 	jnz	short namei_0
  3609                              <1> 	; 12/10/2015
  3610 000049F5 E80F010000          <1> 	call	trans_addr_nmbp ; convert virtual address to physical
  3611                              <1> 		; esi = physical address (page start + offset)
  3612                              <1> 		; ecx = byte count in the page
  3613 000049FA 4E                  <1> 	dec	esi
  3614                              <1> namei_0:
  3615 000049FB 46                  <1> 	inc 	esi  ; go to next char
  3616 000049FC 66A1[886E0000]      <1> 	mov	ax, [rootdir] ; 09/07/2013
  3617                              <1> 		; mov rootdir,r1 / put i-number of rootdirectory in r1
  3618 00004A02 C605[7F6E0000]00    <1> 	mov	byte [cdev], 0
  3619                              <1> 		; clr cdev / clear device number
  3620                              <1> namei_1: ; 1:
  3621 00004A09 F606FF              <1> 	test	byte [esi], 0FFh
  3622                              <1> namei_10: ; 24/12/2021 (jump from namei_8)
  3623 00004A0C 74C1                <1> 	jz	short getf4
  3624                              <1> 	;jz	nig
  3625                              <1> 		; tstb *u.namep / is the character in file name a nul
  3626                              <1> 		; beq nig / yes, end of file name reached; 
  3627                              <1> 			; / branch to "nig"
  3628                              <1> namei_2: ; 1:
  3629                              <1> 	; 18/10/2015
  3630 00004A0E 8935[106F0000]      <1> 	mov 	[nbase], esi
  3631 00004A14 66890D[146F0000]    <1> 	mov 	[ncount], cx
  3632                              <1> 	;
  3633                              <1> 	;mov	dx, 2
  3634 00004A1B B202                <1> 	mov	dl, 2 ; user flag (read, non-owner)
  3635 00004A1D E84C080000          <1> 	call	access
  3636                              <1> 		; jsr r0,access; 2 / get i-node with i-number r1
  3637                              <1> 	; 'access' will not return here if user has not "r" permission !
  3638                              <1> 	; 03/02/2022
  3639 00004A22 F605[996B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3640                              <1> 	;test 	word [i.flgs], 4000h
  3641                              <1> 		; bit $40000,i.flgs / directory i-node?
  3642 00004A29 746A                <1>         jz      short namei_err
  3643                              <1> 		; beq error3 / no, got an error
  3644                              <1> 	; 16/06/2015 - 32 bit modifications (Retro UNIX 386 v1)
  3645 00004A2B 31C0                <1> 	xor	eax, eax
  3646 00004A2D A3[B46E0000]        <1> 	mov	[u.off], eax ; 0
  3647 00004A32 66A1[9C6B0000]      <1> 	mov	ax, [i.size]
  3648 00004A38 A3[AC6E0000]        <1> 	mov	[u.dirp], eax
  3649                              <1> 		; mov i.size,u.dirp / put size of directory in u.dirp
  3650                              <1> 		; clr u.off / u.off is file offset used by user
  3651 00004A3D C705[A86E0000]-     <1> 	mov	dword [u.fofp], u.off
  3651 00004A43 [B46E0000]          <1>
  3652                              <1> 		; mov $u.off,u.fofp / u.fofp is a pointer to 
  3653                              <1> 				  ; / the offset portion of fsp entry
  3654                              <1> namei_3: ; 2:
  3655 00004A47 C705[B86E0000]-     <1> 	mov	dword [u.base], u.dirbuf
  3655 00004A4D [CA6E0000]          <1>
  3656                              <1> 		; mov $u.dirbuf,u.base / u.dirbuf holds a file name 
  3657                              <1> 				    ; / copied from a directory
  3658 00004A51 C705[BC6E0000]1000- <1> 	mov 	dword [u.count], 16 ; 04/12/2015 (10 -> 16) 	
  3658 00004A59 0000                <1>
  3659                              <1>  		; mov $10.,u.count / u.count is byte count 
  3660                              <1> 				 ; / for reads and writes
  3661 00004A5B 66A1[7C6E0000]      <1> 	mov 	ax, [ii]
  3662                              <1> 	; 31/07/2013 ('namei_r') - 16/06/2015 ('u.kcall')
  3663 00004A61 FE05[FF6E0000]      <1>  	inc     byte [u.kcall] ; the caller is 'namei' sign	
  3664 00004A67 E802090000          <1>     	call	readi
  3665                              <1> 		; jsr r0,readi / read 10. bytes of file 
  3666                              <1> 		      ; with i-number (r1); i.e. read a directory entry
  3667 00004A6C 8B0D[C06E0000]      <1> 	mov 	ecx, [u.nread]
  3668 00004A72 09C9                <1> 	or 	ecx, ecx
  3669                              <1> 		; tst u.nread
  3670 00004A74 741B                <1> 	jz	short nib
  3671                              <1> 		; ble nib / gives error return
  3672                              <1> 	;
  3673 00004A76 668B1D[CA6E0000]    <1> 	mov 	bx, [u.dirbuf]
  3674 00004A7D 6621DB              <1> 	and 	bx, bx       
  3675                              <1> 		; tst u.dirbuf /
  3676 00004A80 7522                <1> 	jnz	short namei_4
  3677                              <1> 		; bne 3f / branch when active directory entry 
  3678                              <1> 		       ; / (i-node word in entry non zero)
  3679 00004A82 A1[B46E0000]        <1> 	mov	eax, [u.off]
  3680 00004A87 83E810              <1> 	sub	eax, 16 ; 04/12/2015 (10 -> 16) 
  3681 00004A8A A3[AC6E0000]        <1> 	mov	[u.dirp], eax
  3682                              <1> 		; mov u.off,u.dirp
  3683                              <1> 		; sub $10.,u.dirp
  3684 00004A8F EBB6                <1> 	jmp	short namei_3
  3685                              <1> 		; br 2b
  3686                              <1> 
  3687                              <1> 	; 18/07/2013
  3688                              <1> nib: 
  3689 00004A91 31C0                <1> 	xor	eax, eax  ; xor ax, ax ; ax = 0 -> file not found 
  3690 00004A93 F9                  <1> 	stc
  3691                              <1> nig:
  3692 00004A94 C3                  <1> 	retn
  3693                              <1> 
  3694                              <1> namei_err:
  3695                              <1> 	; 16/06/2015
  3696 00004A95 C705[ED6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a directory !' error
  3696 00004A9D 0000                <1>
  3697 00004A9F E92EF0FFFF          <1> 	jmp	error
  3698                              <1> 
  3699                              <1> namei_4: ; 3:
  3700                              <1> 	; 18/10/2015
  3701                              <1> 	; 12/10/2015
  3702                              <1> 	; 21/08/2015
  3703                              <1> 	; 18/07/2015
  3704 00004AA4 8B2D[B06E0000]      <1> 	mov	ebp, [u.namep]
  3705                              <1> 		; mov u.namep,r2 / u.namep points into a file name string
  3706 00004AAA BF[CC6E0000]        <1> 	mov 	edi, u.dirbuf + 2
  3707                              <1> 		; mov $u.dirbuf+2,r3 / points to file name of directory entry
  3708                              <1> 	; 18/10/2015
  3709 00004AAF 8B35[106F0000]      <1> 	mov	esi, [nbase]	
  3710 00004AB5 668B0D[146F0000]    <1> 	mov	cx, [ncount]
  3711                              <1> 	;
  3712 00004ABC 6621C9              <1> 	and	cx, cx
  3713 00004ABF 7505                <1> 	jnz	short namei_5	
  3714                              <1> 	;
  3715 00004AC1 E849000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3716                              <1> 		; esi = physical address (page start + offset)
  3717                              <1> 		; ecx = byte count in the page
  3718                              <1> namei_5: ; 3:
  3719 00004AC6 45                  <1> 	inc	ebp ; 18/07/2015
  3720 00004AC7 AC                  <1> 	lodsb   ; mov al, [esi] ; inc esi (al = r4)
  3721                              <1> 		; movb (r2)+,r4 / move a character from u.namep string into r4
  3722 00004AC8 08C0                <1> 	or 	al, al
  3723 00004ACA 741C                <1> 	jz 	short namei_7
  3724                              <1> 		; beq 3f / if char is nul, then the last char in string
  3725                              <1> 			; / has been moved
  3726 00004ACC 3C2F                <1> 	cmp	al, '/'
  3727                              <1> 		; cmp r4,$'/ / is char a </>
  3728 00004ACE 7418                <1> 	je 	short namei_7
  3729                              <1> 		; beq 3f	
  3730                              <1> 	; 24/12/2021
  3731 00004AD0 49                  <1> 	dec	ecx
  3732                              <1> 	; 12/10/2015
  3733                              <1> 	;dec	cx ; remain byte count in the page
  3734 00004AD1 7505                <1> 	jnz	short namei_6
  3735 00004AD3 E837000000          <1> 	call	trans_addr_nm ; convert virtual address to physical
  3736                              <1> 		; esi = physical address (page start + offset)
  3737                              <1> 		; ecx = byte count in the page
  3738                              <1> namei_6:
  3739 00004AD8 81FF[DA6E0000]      <1>         cmp     edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3740                              <1> 		; cmp r3,$u.dirbuf+10. / have I checked
  3741                              <1> 				     ; / all 8 bytes of file name
  3742 00004ADE 74E6                <1> 	je	short namei_5
  3743                              <1> 		; beq 3b
  3744 00004AE0 AE                  <1> 	scasb	
  3745                              <1> 		; cmpb (r3)+,r4 / compare char in u.namep string to file name 
  3746                              <1> 			      ; / char read from directory
  3747 00004AE1 74E3                <1> 	je 	short namei_5
  3748                              <1> 		; beq 3b / branch if chars match
  3749                              <1> namei_9:
  3750 00004AE3 E95FFFFFFF          <1>         jmp	namei_3 ; 2b
  3751                              <1> 		; br 2b / file names do not match go to next directory entry
  3752                              <1> namei_7: ; 3:
  3753 00004AE8 81FF[DA6E0000]      <1> 	cmp	edi, u.dirbuf + 16 ; 04/12/2015 (10 -> 16) 
  3754                              <1> 		; cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
  3755 00004AEE 7406                <1> 	je	short namei_8
  3756                              <1> 		; beq 3f
  3757 00004AF0 8A27                <1> 	mov 	ah, [edi]
  3758                              <1> 	;inc 	edi 
  3759 00004AF2 20E4                <1> 	and 	ah, ah
  3760                              <1> 		; tstb (r3)+ /
  3761                              <1>         ;jnz	namei_3
  3762                              <1> 		; bne 2b
  3763                              <1> 	; 24/12/2021
  3764 00004AF4 75ED                <1> 	jnz	short namei_9	
  3765                              <1> namei_8: ; 3
  3766 00004AF6 892D[B06E0000]      <1> 	mov	[u.namep], ebp ; 18/07/2015
  3767                              <1> 		; mov r2,u.namep / u.namep points to char 
  3768                              <1> 			       ; / following a / or nul
  3769                              <1> 	;mov	bx, [u.dirbuf]
  3770                              <1> 		; mov u.dirbuf,r1 / move i-node number in directory 
  3771                              <1> 				; / entry to r1
  3772 00004AFC 20C0                <1> 	and 	al, al
  3773                              <1> 		; tst r4 / if r4 = 0 the end of file name reached,
  3774                              <1> 		      ;  / if r4 = </> then go to next directory
  3775                              <1> 	;mov	ax, bx
  3776 00004AFE 66A1[CA6E0000]      <1> 	mov 	ax, [u.dirbuf] ; 17/06/2015
  3777                              <1>   	; 24/12/2021
  3778 00004B04 E903FFFFFF          <1> 	jmp	namei_10 ; (jnz short namei_2, retn)
  3779                              <1> 	;jnz	namei_2 
  3780                              <1> 		; bne 1b
  3781                              <1> 	; AX = i-number of the file
  3782                              <1> ;;nig:
  3783                              <1> 	;retn	; 24/12/2021
  3784                              <1> 		; tst (r0)+ / gives non-error return
  3785                              <1> ;;nib:
  3786                              <1> ;;	xor	ax, ax ; Retro UNIX 8086 v1 modification !
  3787                              <1> 		       ; ax = 0 -> file not found 
  3788                              <1> ;;	stc	; 27/05/2013
  3789                              <1> ;;	retn
  3790                              <1> 		; rts r0
  3791                              <1> 
  3792                              <1> trans_addr_nmbp:
  3793                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  3794                              <1> 	; 18/10/2015
  3795                              <1> 	; 12/10/2015
  3796 00004B09 8B2D[B06E0000]      <1> 	mov 	ebp, [u.namep]
  3797                              <1> trans_addr_nm:
  3798                              <1> 	; 08/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2) 
  3799                              <1> 	; Convert virtual (pathname) address to physical address
  3800                              <1> 	; (Retro UNIX 386 v1 feature only !)
  3801                              <1> 	; 18/10/2015
  3802                              <1> 	; 12/10/2015 (u.pnbase & u.pncount has been removed from code)
  3803                              <1> 	; 02/07/2015
  3804                              <1> 	; 17/06/2015
  3805                              <1> 	; 16/06/2015
  3806                              <1> 	;
  3807                              <1> 	; INPUTS: 
  3808                              <1> 	;	ebp = pathname address (virtual) ; [u.namep]
  3809                              <1> 	;	[u.pgdir] = user's page directory
  3810                              <1> 	; OUTPUT:
  3811                              <1> 	;       esi = physical address of the pathname
  3812                              <1> 	;	ecx = remain byte count in the page
  3813                              <1> 	;
  3814                              <1> 	; (Modified registers: EAX, EBX, ECX, EDX, ESI)
  3815                              <1> 	;
  3816                              <1> 
  3817                              <1> 	; 08/01/2022
  3818 00004B0F 29C9                <1> 	sub	ecx, ecx
  3819                              <1> 	;
  3820 00004B11 833D[F56E0000]00    <1>         cmp     dword [u.ppgdir], 0  ; /etc/init ? (sysexec)
  3821 00004B18 7618                <1> 	jna	short trans_addr_nmk ; the caller is os kernel;
  3822                              <1> 				     ; it is already physical address
  3823 00004B1A 50                  <1>    	push	eax	
  3824 00004B1B 89EB                <1> 	mov	ebx, ebp ; [u.namep] ; pathname address (virtual)
  3825 00004B1D E880E6FFFF          <1>        	call	get_physical_addr ; get physical address
  3826 00004B22 7204                <1> 	jc	short tr_addr_nm_err
  3827                              <1> 	; 18/10/2015
  3828                              <1> 	; eax = physical address 
  3829                              <1> 	; cx = remain byte count in page (1-4096) 
  3830                              <1> 		; 12/10/2015 (cx = [u.pncount])
  3831 00004B24 89C6                <1> 	mov	esi, eax ; 12/10/2015 (esi=[u.pnbase])
  3832 00004B26 58                  <1> 	pop	eax 
  3833 00004B27 C3                  <1> 	retn
  3834                              <1> 
  3835                              <1> tr_addr_nm_err:
  3836 00004B28 A3[ED6E0000]        <1> 	mov	[u.error], eax
  3837                              <1> 	;pop 	eax
  3838 00004B2D E9A0EFFFFF          <1> 	jmp	error
  3839                              <1> 
  3840                              <1> trans_addr_nmk:
  3841                              <1> 	; 12/10/2015
  3842                              <1> 	; 02/07/2015
  3843 00004B32 8B35[B06E0000]      <1> 	mov	esi, [u.namep]  ; [u.pnbase]
  3844                              <1> 	;mov	cx, PAGE_SIZE ; 4096 ; [u.pncount]
  3845                              <1> 	; 08/01/2022
  3846 00004B38 B510                <1> 	mov	ch, PAGE_SIZE/256
  3847 00004B3A C3                  <1> 	retn
  3848                              <1> 
  3849                              <1> syschdir:
  3850                              <1> 	; / makes the directory specified in the argument
  3851                              <1> 	; / the current directory
  3852                              <1> 	;
  3853                              <1> 	; 09/01/2022
  3854                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3855                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3856                              <1> 	; 19/06/2013 (Retro UNIX 8086 v1)
  3857                              <1> 	;
  3858                              <1> 	; 'syschdir' makes the directory specified in its argument
  3859                              <1> 	; the current working directory.
  3860                              <1> 	;
  3861                              <1> 	; Calling sequence:
  3862                              <1> 	;	syschdir; name
  3863                              <1> 	; Arguments:
  3864                              <1> 	;	name - address of the path name of a directory
  3865                              <1> 	;	       terminated by nul byte.	
  3866                              <1> 	; Inputs: -
  3867                              <1> 	; Outputs: -
  3868                              <1> 	; ...............................................................
  3869                              <1> 	;				
  3870                              <1> 	; Retro UNIX 8086 v1 modification:
  3871                              <1> 	;	 The user/application program puts address of 
  3872                              <1> 	;	 the path name in BX register as 'syschdir' 
  3873                              <1> 	; 	 system call argument.
  3874                              <1> 
  3875 00004B3B 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  3876                              <1> 		; jsr r0,arg; u.namep / u.namep points to path name
  3877 00004B41 E88AFEFFFF          <1> 	call	namei
  3878                              <1> 		; jsr r0,namei / find its i-number
  3879                              <1> 	;jc	error
  3880                              <1> 		; br error3
  3881 00004B46 730F                <1> 	jnc	short syschdir0
  3882                              <1> 	; 'directory not found !' error
  3883 00004B48 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_DIR_NOT_FOUND ; 12
  3883 00004B50 0000                <1>
  3884 00004B52 E97BEFFFFF          <1> 	jmp	error
  3885                              <1> syschdir0:
  3886                              <1> 	; 08/01/2022
  3887 00004B57 B202                <1> 	mov	dl, 2  ; read access ; 08/01/2022 (BugFix)
  3888 00004B59 E810070000          <1> 	call	access
  3889                              <1> 		; jsr r0,access; 2 / get i-node into core
  3890                              <1> 	; 08/01/2022
  3891 00004B5E F605[996B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3892                              <1> 	;test	word [i.flgs], 4000h
  3893                              <1> 		; bit $40000,i.flgs / is it a directory?
  3894                              <1> 	;jz	error 
  3895                              <1> 		; beq error3 / no error
  3896 00004B65 750F                <1> 	jnz	short syschdir1
  3897 00004B67 C705[ED6E0000]1300- <1> 	mov	dword [u.error], ERR_NOT_DIR ; 'not a valid directory !'
  3897 00004B6F 0000                <1>
  3898 00004B71 E95CEFFFFF          <1> 	jmp	error
  3899                              <1> syschdir1:
  3900 00004B76 66A3[9C6E0000]      <1> 	mov	[u.cdir], ax
  3901                              <1> 		; mov r1,u.cdir / move i-number to users 
  3902                              <1> 			      ; / current directory
  3903                              <1> 	; 09/01/2022
  3904 00004B7C A0[7F6E0000]        <1> 	mov	al, [cdev]
  3905 00004B81 A2[E26E0000]        <1> 	mov	[u.cdrv], al
  3906                              <1> 	;mov	ax, [cdev]
  3907                              <1> 	;mov	[u.cdrv], ax
  3908                              <1> 		; mov cdev,u.cdev / move its device to users 
  3909                              <1> 			        ; / current device
  3910 00004B86 E967EFFFFF          <1> 	jmp	sysret
  3911                              <1> 		; br sysret3
  3912                              <1> 
  3913                              <1> syschmod: ; < change mode of file >
  3914                              <1> 	; 29/04/2022 (bugfix)
  3915                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  3916                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  3917                              <1> 	; 20/06/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3918                              <1> 	;
  3919                              <1> 	; 'syschmod' changes mode of the file whose name is given as
  3920                              <1> 	; null terminated string pointed to by 'name' has it's mode 
  3921                              <1> 	; changed to 'mode'.
  3922                              <1> 	;
  3923                              <1> 	; Calling sequence:
  3924                              <1> 	;	syschmod; name; mode
  3925                              <1> 	; Arguments:
  3926                              <1> 	;	name - address of the file name
  3927                              <1> 	;	       terminated by null byte.
  3928                              <1> 	;	mode - (new) mode/flags < attributes >
  3929                              <1> 	;	
  3930                              <1> 	; Inputs: -
  3931                              <1> 	; Outputs: -
  3932                              <1> 	; ...............................................................
  3933                              <1> 	;				
  3934                              <1> 	; Retro UNIX 8086 v1 modification: 
  3935                              <1> 	;       'syschmod' system call has two arguments; so,
  3936                              <1> 	;	* 1st argument, name is pointed to by BX register
  3937                              <1> 	;	* 2nd argument, mode is in CX register
  3938                              <1> 	;
  3939                              <1> 	; Mode bits (Flags):
  3940                              <1> 	;	bit 15 - 'i-node is allocated' flag (8000h)
  3941                              <1> 	;	bit 14 - directory flag (4000h)
  3942                              <1> 	;	bit 13 - file has modified flag (always on) (2000h)
  3943                              <1> 	;	bit 12 - large file flag (1000h)
  3944                              <1> 	;	bit 6,7,8,9,10,11 are not used (undefined)
  3945                              <1> 	;	bit 5 - set user ID on execution flag (20h) 
  3946                              <1> 	;	bit 4 - executable flag (10h)
  3947                              <1> 	;	bit 3 - read permission for owner (08h)
  3948                              <1> 	;	bit 2 - write permission for owner (04h)
  3949                              <1> 	;	bit 1 - read permission for non-owner (02h)
  3950                              <1> 	;	bit 0 - write permission for non-owner (01h)
  3951                              <1> 
  3952                              <1> 	; / name; mode
  3953 00004B8B E815000000          <1> 	call	isown
  3954                              <1> 		;jsr r0,isown / get the i-node and check user status
  3955                              <1> 	; 09/01/2022
  3956 00004B90 F605[996B0000]40    <1> 	test	byte [i.flgs+1], 40h
  3957                              <1> 	;test	word [i.flgs], 4000h
  3958                              <1> 		; bit $40000,i.flgs / directory?
  3959 00004B97 7402                <1> 	jz	short syschmod1
  3960                              <1> 		; beq 2f / no
  3961                              <1> 	; AL = (new) mode
  3962 00004B99 24CF                <1> 	and	al, 0CFh ; 11001111b (clears bit 4 & 5)
  3963                              <1> 		; bic $60,r2 / su & ex / yes, clear set user id and 
  3964                              <1> 			   ; / executable modes
  3965                              <1> syschmod1: ; 2:
  3966 00004B9B A2[986B0000]        <1> 	mov	[i.flgs], al	
  3967                              <1> 		; movb r2,i.flgs / move remaining mode to i.flgs
  3968                              <1> 	;jmp	short isown1
  3969                              <1> 	;	; br 1f ; (jmp sysret4)
  3970                              <1> 	; 29/04/2022
  3971 00004BA0 E94DEFFFFF          <1> 	jmp	sysret
  3972                              <1> 
  3973                              <1> isown:
  3974                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  3975                              <1> 	; 04/05/2013 - 07/07/2013 (Retro UNIX 8086 v1)
  3976                              <1> 	;
  3977                              <1> 	; 'isown' is given a file name (the 1st argument).
  3978                              <1> 	;  It find the i-number of that file via 'namei' 
  3979                              <1> 	;  then gets the i-node into core via 'iget'.
  3980                              <1> 	;  It then tests to see if the user is super user. 
  3981                              <1> 	;  If not, it cheks to see if the user is owner of 
  3982                              <1> 	;  the file. If he is not an error occurs.
  3983                              <1> 	;  If user is the owner 'setimod' is called to indicate
  3984                              <1> 	;  the inode has been modified and the 2nd argument of
  3985                              <1> 	;  the call is put in r2.
  3986                              <1> 	;
  3987                              <1> 	; INPUTS ->
  3988                              <1> 	;    arguments of syschmod and syschown calls
  3989                              <1> 	; OUTPUTS ->
  3990                              <1> 	;    u.uid - id of user
  3991                              <1> 	;    imod - set to a 1
  3992                              <1> 	;    r2 - contains second argument of the system call				 	
  3993                              <1> 	;
  3994                              <1> 	;   ((AX=R2) output as 2nd argument)
  3995                              <1> 	;
  3996                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  3997                              <1> 	;
  3998                              <1> 		; jsr r0,arg2 / u.namep points to file name
  3999                              <1> 	;; ! 2nd argument on top of stack !
  4000                              <1> 	;; 22/06/2015 - 32 bit modifications
  4001                              <1> 	;; 07/07/2013
  4002 00004BA5 891D[B06E0000]      <1> 	mov	[u.namep], ebx ;; 1st argument
  4003 00004BAB 51                  <1> 	push 	ecx ;; 2nd argument
  4004                              <1> 	;;
  4005 00004BAC E81FFEFFFF          <1> 	call	namei
  4006                              <1> 		; jsr r0,namei / get its i-number
  4007                              <1>        ; Retro UNIX 8086 v1 modification !
  4008                              <1>        ; ax = 0 -> file not found 
  4009                              <1> 	;and	ax, ax
  4010                              <1> 	;jz	error
  4011                              <1> 	;jc	error ; 27/05/2013
  4012                              <1> 		; br error3
  4013 00004BB1 730F                <1> 	jnc	short isown0
  4014                              <1> 	; 'file not found !' error
  4015 00004BB3 C705[ED6E0000]0C00- <1> 	mov	dword [u.error], ERR_FILE_NOT_FOUND ; 12
  4015 00004BBB 0000                <1>
  4016 00004BBD E910EFFFFF          <1> 	jmp	error
  4017                              <1> isown0:
  4018 00004BC2 E8D3050000          <1> 	call	iget
  4019                              <1> 		; jsr r0,iget / get i-node into core
  4020 00004BC7 A0[E46E0000]        <1> 	mov	al, [u.uid] ; 02/08/2013
  4021 00004BCC 08C0                <1> 	or	al, al
  4022                              <1> 		; tstb u.uid / super user?
  4023 00004BCE 7417                <1> 	jz	short isown1
  4024                              <1> 		; beq 1f / yes, branch
  4025 00004BD0 3A05[9B6B0000]      <1> 	cmp	al, [i.uid]
  4026                              <1> 		; cmpb i.uid,u.uid / no, is this the owner of
  4027                              <1> 				 ; / the file
  4028                              <1> 	;jne	error
  4029                              <1> 		; beq 1f / yes
  4030                              <1> 		; jmp error3 / no, error
  4031 00004BD6 740F                <1> 	je	short isown1
  4032                              <1> 
  4033 00004BD8 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_OWNER  ; 11
  4033 00004BE0 0000                <1>
  4034                              <1> 			;  'permission denied !' error
  4035 00004BE2 E9EBEEFFFF          <1> 	jmp	error
  4036                              <1> isown1: ; 1:
  4037 00004BE7 E8B8060000          <1> 	call	setimod
  4038                              <1> 		; jsr r0,setimod / indicates 
  4039                              <1> 		;	       ; / i-node has been modified
  4040 00004BEC 58                  <1> 	pop	eax ; 2nd argument
  4041                              <1> 		; mov (sp)+,r2 / mode is put in r2 
  4042                              <1> 		       ; / (u.off put on stack with 2nd arg)
  4043 00004BED C3                  <1> 	retn
  4044                              <1> 		; rts r0
  4045                              <1> 
  4046                              <1> ;;arg:  ; < get system call arguments >
  4047                              <1> 	; 'arg' extracts an argument for a routine whose call is 
  4048                              <1> 	; of form:
  4049                              <1> 	;	sys 'routine' ; arg1
  4050                              <1> 	;		or
  4051                              <1> 	;	sys 'routine' ; arg1 ; arg2
  4052                              <1> 	;		or
  4053                              <1> 	;	sys 'routine' ; arg1;...;arg10 (sys exec) 
  4054                              <1> 	;	
  4055                              <1> 	; INPUTS ->
  4056                              <1> 	;    u.sp+18 - contains a pointer to one of arg1..argn
  4057                              <1> 	;	This pointers's value is actually the value of
  4058                              <1> 	;	update pc at the the trap to sysent (unkni) is
  4059                              <1> 	;	made to process the sys instruction
  4060                              <1> 	;    r0 - contains the return address for the routine
  4061                              <1> 	;	that called arg. The data in the word pointer 
  4062                              <1> 	;	to by the return address is used as address
  4063                              <1> 	;	in which the extracted argument is stored   		
  4064                              <1> 	;    	
  4065                              <1> 	; OUTPUTS ->
  4066                              <1> 	;    'address' - contains the extracted argument 
  4067                              <1> 	;    u.sp+18 - is incremented by 2 
  4068                              <1> 	;    r1 - contains the extracted argument
  4069                              <1> 	;    r0 - points to the next instruction to be
  4070                              <1> 	;	 executed in the calling routine.
  4071                              <1> 	;
  4072                              <1>   
  4073                              <1> 	; mov u.sp,r1
  4074                              <1> 	; mov *18.(r1),*(r0)+ / put argument of system call
  4075                              <1> 			; / into argument of arg2
  4076                              <1> 	; add $2,18.(r1) / point pc on stack 
  4077                              <1> 			      ; / to next system argument
  4078                              <1> 	; rts r0
  4079                              <1> 
  4080                              <1> ;;arg2: ; < get system calls arguments - with file name pointer>
  4081                              <1> 	; 'arg2' takes first argument in system call
  4082                              <1> 	;  (pointer to name of the file) and puts it in location
  4083                              <1> 	;  u.namep; takes second argument and puts it in u.off
  4084                              <1> 	;  and on top of the stack
  4085                              <1> 	;	
  4086                              <1> 	; INPUTS ->
  4087                              <1> 	;    u.sp, r0
  4088                              <1> 	;    	
  4089                              <1> 	; OUTPUTS ->
  4090                              <1> 	;    u.namep
  4091                              <1> 	;    u.off 
  4092                              <1> 	;    u.off pushed on stack
  4093                              <1> 	;    r1
  4094                              <1> 	;
  4095                              <1> 
  4096                              <1> 	; jsr	r0,arg; u.namep / u.namep contains value of
  4097                              <1> 				; / first arg in sys call
  4098                              <1> 	; jsr r0,arg; u.off / u.off contains value of 
  4099                              <1> 				; / second arg in sys call
  4100                              <1> 	; mov r0,r1 / r0 points to calling routine
  4101                              <1> 	; mov (sp),r0 / put operation code back in r0
  4102                              <1> 	; mov u.off,(sp) / put pointer to second argument 
  4103                              <1> 			; / on stack
  4104                              <1> 	; jmp (r1) / return to calling routine
  4105                              <1> 
  4106                              <1> syschown: ; < change owner of file >
  4107                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4108                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4109                              <1> 	;
  4110                              <1> 	; 'syschown' changes the owner of the file whose name is given
  4111                              <1> 	; as null terminated string pointed to by 'name' has it's owner
  4112                              <1> 	; changed to 'owner'
  4113                              <1> 	;
  4114                              <1> 	; Calling sequence:
  4115                              <1> 	;	syschown; name; owner
  4116                              <1> 	; Arguments:
  4117                              <1> 	;	name - address of the file name
  4118                              <1> 	;	       terminated by null byte.
  4119                              <1> 	;	owner - (new) owner (number/ID)
  4120                              <1> 	;	
  4121                              <1> 	; Inputs: -
  4122                              <1> 	; Outputs: -
  4123                              <1> 	; ...............................................................
  4124                              <1> 	;				
  4125                              <1> 	; Retro UNIX 8086 v1 modification: 
  4126                              <1> 	;       'syschown' system call has two arguments; so,
  4127                              <1> 	;	* 1st argument, name is pointed to by BX register
  4128                              <1> 	;	* 2nd argument, owner number is in CX register
  4129                              <1> 	;
  4130                              <1> 	; / name; owner
  4131 00004BEE E8B2FFFFFF          <1> 	call	isown
  4132                              <1> 		; jsr r0,isown / get the i-node and check user status
  4133 00004BF3 803D[E46E0000]00    <1> 	cmp 	byte [u.uid], 0 ; 02/08/2013 
  4134                              <1> 		; tstb u.uid / super user
  4135 00004BFA 7418                <1> 	jz	short syschown1
  4136                              <1> 		; beq 2f / yes, 2f
  4137 00004BFC F605[986B0000]20    <1>         test    byte [i.flgs], 20h ; 32
  4138                              <1> 		; bit $40,i.flgs / no, set userid on execution?
  4139                              <1> 	;jnz	error
  4140                              <1> 		; bne 3f / yes error, could create Trojan Horses
  4141 00004C03 740F                <1> 	jz	short syschown1
  4142                              <1> 	; 'permission denied !'
  4143 00004C05 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS  ; 11
  4143 00004C0D 0000                <1>
  4144 00004C0F E9BEEEFFFF          <1> 	jmp	error
  4145                              <1> syschown1: ; 2:
  4146                              <1> 	; AL = owner (number/ID)
  4147 00004C14 A2[9B6B0000]        <1> 	mov	[i.uid], al ; 23/06/2015
  4148                              <1> 		;  movb	r2,i.uid / no, put the new owners id 
  4149                              <1> 			       ; / in the i-node
  4150 00004C19 E9D4EEFFFF          <1> 	jmp	sysret
  4151                              <1> 	; 1: 
  4152                              <1> 		; jmp sysret4
  4153                              <1> 	; 3:
  4154                              <1> 		; jmp	error
  4155                              <1> 
  4156                              <1> systime: ; / get time of year
  4157                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4158                              <1> 	; 20/06/2013 (Retro UNIX 8086 v1)
  4159                              <1> 	;
  4160                              <1> 	; 20/06/2013
  4161                              <1> 	; 'systime' gets the time of the year.
  4162                              <1> 	; The present time is put on the stack.
  4163                              <1> 	;
  4164                              <1> 	; Calling sequence:
  4165                              <1> 	;	systime
  4166                              <1> 	; Arguments: -
  4167                              <1> 	;	
  4168                              <1> 	; Inputs: -
  4169                              <1> 	; Outputs: sp+2, sp+4 - present time
  4170                              <1> 	; ...............................................................
  4171                              <1> 	;	
  4172                              <1> 	; Retro UNIX 8086 v1 modification: 
  4173                              <1> 	;       'systime' system call will return to the user
  4174                              <1> 	;	with unix time (epoch) in DX:AX register pair
  4175                              <1> 	;
  4176                              <1> 	; 	!! Major modification on original Unix v1 'systime' 
  4177                              <1> 	;	system call for PC compatibility !!		 	
  4178                              <1> 
  4179 00004C1E E8F2E9FFFF          <1> 	call 	epoch
  4180 00004C23 A3[986E0000]        <1> 	mov 	[u.r0], eax
  4181                              <1> 		; mov s.time,4(sp)
  4182                              <1> 		; mov s.time+2,2(sp) / put the present time 
  4183                              <1> 				   ; / on the stack
  4184                              <1> 		; br sysret4
  4185 00004C28 E9C5EEFFFF          <1> 	jmp	sysret 
  4186                              <1> 
  4187                              <1> sysstime: ; / set time
  4188                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4189                              <1> 	; 20/06/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4190                              <1> 	;
  4191                              <1> 	; 'sysstime' sets the time. Only super user can use this call.
  4192                              <1> 	;
  4193                              <1> 	; Calling sequence:
  4194                              <1> 	;	sysstime
  4195                              <1> 	; Arguments: -
  4196                              <1> 	;	
  4197                              <1> 	; Inputs: sp+2, sp+4 - time system is to be set to.
  4198                              <1> 	; Outputs: -
  4199                              <1> 	; ...............................................................
  4200                              <1> 	;	
  4201                              <1> 	; Retro UNIX 8086 v1 modification: 
  4202                              <1> 	;	the user calls 'sysstime' with unix (epoch) time
  4203                              <1> 	;	(to be set) is in CX:BX register pair as two arguments.
  4204                              <1> 	; 
  4205                              <1> 	;	Retro UNIX 8086 v1 argument transfer method 2 is used
  4206                              <1> 	;	to get sysstime system call arguments from the user;
  4207                              <1> 	;	* 1st argument, lowword of unix time is in BX register
  4208                              <1> 	;	* 2nd argument, highword of unix time is in CX register		 	
  4209                              <1> 	;
  4210                              <1> 	; 	!! Major modification on original Unix v1 'sysstime' 
  4211                              <1> 	;	system call for PC compatibility !!	
  4212                              <1> 
  4213 00004C2D 803D[E46E0000]00    <1> 	cmp	byte [u.uid], 0
  4214                              <1> 		; tstb u.uid / is user the super user
  4215                              <1> 	;ja	error
  4216                              <1> 		; bne error4 / no, error
  4217 00004C34 760F                <1> 	jna	short systime1
  4218                              <1> 	; 'permission denied !'
  4219 00004C36 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11 
  4219 00004C3E 0000                <1>
  4220 00004C40 E98DEEFFFF          <1> 	jmp	error
  4221                              <1> systime1:
  4222                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - 32 bit version)
  4223                              <1> 	; EBX = unix (epoch) time (from user)
  4224 00004C45 89D8                <1> 	mov	eax, ebx
  4225 00004C47 E849EBFFFF          <1> 	call 	set_date_time
  4226                              <1> 		; mov 4(sp),s.time
  4227                              <1> 		; mov 2(sp),s.time+2 / set the system time
  4228 00004C4C E9A1EEFFFF          <1> 	jmp	sysret
  4229                              <1> 		; br sysret4
  4230                              <1> 
  4231                              <1> sysbreak:
  4232                              <1> 	; 18/10/2015
  4233                              <1> 	; 07/10/2015
  4234                              <1> 	; 23/06/2015 (Retro UNIX 386 v1 - Beginning)
  4235                              <1> 	; 20/06/2013 - 24/03/2014 (Retro UNIX 8086 v1)
  4236                              <1> 	;
  4237                              <1> 	; 'sysbreak' sets the programs break points. 
  4238                              <1> 	; It checks the current break point (u.break) to see if it is
  4239                              <1> 	; between "core" and the stack (sp). If it is, it is made an
  4240                              <1> 	; even address (if it was odd) and the area between u.break
  4241                              <1> 	; and the stack is cleared. The new breakpoint is then put
  4242                              <1> 	; in u.break and control is passed to 'sysret'.
  4243                              <1> 	;
  4244                              <1> 	; Calling sequence:
  4245                              <1> 	;	sysbreak; addr
  4246                              <1> 	; Arguments: -
  4247                              <1> 	;	
  4248                              <1> 	; Inputs: u.break - current breakpoint
  4249                              <1> 	; Outputs: u.break - new breakpoint 
  4250                              <1> 	;	area between old u.break and the stack (sp) is cleared.
  4251                              <1> 	; ...............................................................
  4252                              <1> 	;	
  4253                              <1> 	; Retro UNIX 8086 v1 modification:
  4254                              <1> 	;	The user/application program puts breakpoint address
  4255                              <1> 	;       in BX register as 'sysbreak' system call argument.
  4256                              <1> 	; 	(argument transfer method 1)
  4257                              <1> 	;
  4258                              <1> 	;  NOTE: Beginning of core is 0 in Retro UNIX 8086 v1 !
  4259                              <1> 	; 	((!'sysbreak' is not needed in Retro UNIX 8086 v1!))
  4260                              <1> 	;  NOTE:
  4261                              <1> 	; 	'sysbreak' clears extended part (beyond of previous
  4262                              <1> 	;	'u.break' address) of user's memory for original unix's
  4263                              <1> 	;	'bss' compatibility with Retro UNIX 8086 v1 (19/11/2013)
  4264                              <1> 
  4265                              <1> 		; mov u.break,r1 / move users break point to r1
  4266                              <1> 		; cmp r1,$core / is it the same or lower than core?
  4267                              <1> 		; blos 1f / yes, 1f
  4268                              <1> 	; 23/06/2015
  4269 00004C51 8B2D[C46E0000]      <1> 	mov	ebp, [u.break] ; virtual address (offset)
  4270                              <1> 	;and	ebp, ebp
  4271                              <1> 	;jz	short sysbreak_3 
  4272                              <1> 	; Retro UNIX 386 v1 NOTE: u.break points to virtual address !!!
  4273                              <1> 	; (Even break point address is not needed for Retro UNIX 386 v1)
  4274 00004C57 8B15[906E0000]      <1> 	mov	edx, [u.sp] ; kernel stack at the beginning of sys call
  4275 00004C5D 83C20C              <1> 	add	edx, 12 ; EIP -4-> CS -4-> EFLAGS -4-> ESP (user) 
  4276                              <1> 	; 07/10/2015
  4277 00004C60 891D[C46E0000]      <1> 	mov	[u.break], ebx ; virtual address !!!
  4278                              <1> 	;
  4279 00004C66 3B1A                <1> 	cmp	ebx, [edx] ; compare new break point with 
  4280                              <1> 			   ; with top of user's stack (virtual!)
  4281 00004C68 7327                <1> 	jnb	short sysbreak_3
  4282                              <1> 		; cmp r1,sp / is it the same or higher 
  4283                              <1> 			  ; / than the stack?
  4284                              <1> 		; bhis 1f / yes, 1f
  4285 00004C6A 89DE                <1> 	mov	esi, ebx
  4286 00004C6C 29EE                <1> 	sub	esi, ebp ; new break point - old break point
  4287 00004C6E 7621                <1> 	jna	short sysbreak_3 
  4288                              <1> 	;push	ebx
  4289                              <1> sysbreak_1:
  4290 00004C70 89EB                <1> 	mov	ebx, ebp  
  4291 00004C72 E82BE5FFFF          <1> 	call	get_physical_addr ; get physical address
  4292 00004C77 0F82ABFEFFFF        <1> 	jc	tr_addr_nm_err
  4293                              <1> 	; 18/10/2015
  4294 00004C7D 89C7                <1> 	mov	edi, eax 
  4295 00004C7F 29C0                <1> 	sub	eax, eax ; 0
  4296                              <1> 		 ; ECX = remain byte count in page (1-4096)
  4297 00004C81 39CE                <1> 	cmp	esi, ecx
  4298 00004C83 7302                <1> 	jnb	short sysbreak_2
  4299 00004C85 89F1                <1> 	mov	ecx, esi
  4300                              <1> sysbreak_2:
  4301 00004C87 29CE                <1> 	sub	esi, ecx
  4302 00004C89 01CD                <1> 	add	ebp, ecx
  4303 00004C8B F3AA                <1> 	rep 	stosb
  4304 00004C8D 09F6                <1> 	or	esi, esi
  4305 00004C8F 75DF                <1> 	jnz	short sysbreak_1
  4306                              <1> 	;
  4307                              <1> 		; bit $1,r1 / is it an odd address
  4308                              <1> 		; beq 2f / no, its even
  4309                              <1> 		; clrb (r1)+ / yes, make it even
  4310                              <1> 	; 2: / clear area between the break point and the stack
  4311                              <1> 		; cmp r1,sp / is it higher or same than the stack
  4312                              <1> 		; bhis 1f / yes, quit
  4313                              <1> 		; clr (r1)+ / clear word
  4314                              <1> 		; br 2b / go back
  4315                              <1> 	;pop	ebx
  4316                              <1> sysbreak_3: ; 1:
  4317                              <1> 	;mov	[u.break], ebx ; virtual address !!!
  4318                              <1> 		; jsr r0,arg; u.break / put the "address" 
  4319                              <1> 			; / in u.break (set new break point)
  4320                              <1> 		; br sysret4 / br sysret
  4321 00004C91 E95CEEFFFF          <1> 	jmp	sysret
  4322                              <1> 
  4323                              <1> maknod: 
  4324                              <1> 	; 11/02/2022
  4325                              <1> 	; 09/01/2022
  4326                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4327                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4328                              <1> 	; 02/05/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4329                              <1> 	;
  4330                              <1> 	; 'maknod' creates an i-node and makes a directory entry
  4331                              <1> 	; for this i-node in the current directory.
  4332                              <1> 	;
  4333                              <1> 	; INPUTS ->
  4334                              <1> 	;    r1 - contains mode
  4335                              <1> 	;    ii - current directory's i-number	
  4336                              <1> 	;    	
  4337                              <1> 	; OUTPUTS ->
  4338                              <1> 	;    u.dirbuf - contains i-number of free i-node 
  4339                              <1> 	;    i.flgs - flags in new i-node 
  4340                              <1> 	;    i.uid - filled with u.uid
  4341                              <1> 	;    i.nlks - 1 is put in the number of links
  4342                              <1> 	;    i.ctim - creation time				
  4343                              <1> 	;    i.ctim+2 - modification time
  4344                              <1> 	;    imod - set via call to setimod
  4345                              <1> 	;	
  4346                              <1> 	; ((AX = R1)) input
  4347                              <1> 	;
  4348                              <1> 	; (Retro UNIX Prototype : 
  4349                              <1> 	;	30/10/2012 - 01/03/2013, UNIXCOPY.ASM)
  4350                              <1>         ; ((Modified registers: eAX, eDX, eBX, eCX, eSI, eDI, eBP))  
  4351                              <1> 
  4352                              <1> 	; / r1 contains the mode
  4353 00004C96 80CC80              <1> 	or 	ah, 80h	; 10000000b
  4354                              <1> 		; bis $100000,r1 / allocate flag set
  4355 00004C99 6650                <1> 	push	ax ; * ; 24/12/2021
  4356                              <1> 		; mov r1,-(sp) / put mode on stack
  4357                              <1> 	; 31/07/2013
  4358 00004C9B 66A1[7C6E0000]      <1> 	mov	ax, [ii] ; move current i-number to AX/r1
  4359                              <1> 		; mov ii,r1 / move current i-number to r1
  4360 00004CA1 B201                <1> 	mov	dl, 1 ; owner flag mask
  4361 00004CA3 E8C6050000          <1> 	call	access	
  4362                              <1> 		; jsr r0,access; 1 / get its i-node into core
  4363 00004CA8 50                  <1> 	push	eax ; ** ; 24/12/2021
  4364                              <1> 		; mov r1,-(sp) / put i-number on stack
  4365 00004CA9 66B82800            <1> 	mov	ax, 40
  4366                              <1> 		; mov $40.,r1 / r1 = 40
  4367                              <1> maknod1: ; 1: / scan for a free i-node (next 4 instructions)
  4368 00004CAD 6640                <1> 	inc	ax
  4369                              <1> 		; inc r1 / r1 = r1 + 1
  4370 00004CAF E87F060000          <1> 	call	imap
  4371                              <1> 		; jsr r0,imap / get byte address and bit position in 
  4372                              <1> 			    ; /	inode map in r2 & m
  4373                              <1>   
  4374                              <1>         ; DX (MQ) has a 1 in the calculated bit position
  4375                              <1>         ; eBX (R2) has byte address of the byte with allocation bit
  4376                              <1> 
  4377                              <1> 	; 22/06/2015 - NOTE for next Retro UNIX version: 
  4378                              <1> 	;	       Inode count must be checked here
  4379                              <1> 	; (Original UNIX v1 did not check inode count here !?) 	
  4380                              <1> 
  4381                              <1> 	; 11/02/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  4382                              <1> 	; (inode count check)
  4383                              <1> 	; ((if cf=1 --> requested inode number > inode count))
  4384                              <1> 
  4385 00004CB4 730F                <1> 	jnc	short maknod2
  4386                              <1> 
  4387                              <1> 	; no free inode in inode table !
  4388 00004CB6 C705[ED6E0000]1B00- <1> 	mov	 dword [u.error], ERR_MISC ; 27
  4388 00004CBE 0000                <1>
  4389                              <1> 			; miscellaneous/other errors
  4390 00004CC0 E90DEEFFFF          <1> 	jmp	error	
  4391                              <1> maknod2: 
  4392 00004CC5 8413                <1> 	test	[ebx], dl
  4393                              <1> 		; bitb mq,(r2) / is the i-node active
  4394 00004CC7 75E4                <1> 	jnz	short maknod1
  4395                              <1> 		; bne 1b / yes, try the next one
  4396 00004CC9 0813                <1> 	or	[ebx], dl
  4397                              <1> 		; bisb mq,(r2) / no, make it active 
  4398                              <1> 			     ; / (put a 1 in the bit map)
  4399 00004CCB E8CA040000          <1> 	call	iget
  4400                              <1> 		; jsr r0,iget / get i-node into core
  4401                              <1> 	; 09/01/2022
  4402 00004CD0 F605[996B0000]80    <1> 	test	byte [i.flgs+1], 80h
  4403                              <1> 	;test	word [i.flgs], 8000h 
  4404                              <1> 		; tst i.flgs / is i-node already allocated
  4405 00004CD7 75D4                <1> 	jnz	short maknod1	
  4406                              <1> 		; blt 1b / yes, look for another one
  4407 00004CD9 66A3[CA6E0000]      <1> 	mov	[u.dirbuf], ax
  4408                              <1> 		; mov r1,u.dirbuf / no, put i-number in u.dirbuf
  4409 00004CDF 58                  <1> 	pop	eax ; ** ; 24/12/2021
  4410                              <1> 		; mov (sp)+,r1 / get current i-number back
  4411 00004CE0 E8B5040000          <1> 	call	iget
  4412                              <1> 		; jsr r0,iget / get i-node in core
  4413 00004CE5 E8ACF7FFFF          <1> 	call	mkdir
  4414                              <1> 		; jsr r0,mkdir / make a directory entry 
  4415                              <1> 			     ; / in current directory
  4416 00004CEA 66A1[CA6E0000]      <1> 	mov	ax, [u.dirbuf]
  4417                              <1> 		; mov u.dirbuf,r1 / r1 = new inode number
  4418 00004CF0 E8A5040000          <1> 	call	iget
  4419                              <1> 		; jsr r0,iget / get it into core
  4420                              <1> 		; jsr r0,copyz; inode; inode+32. / 0 it out
  4421                              <1> 	;mov	ecx, 8
  4422                              <1> 	; 09/01/2022 
  4423 00004CF5 29C9                <1> 	sub	ecx, ecx
  4424 00004CF7 B108                <1> 	mov	cl, 8
  4425 00004CF9 31C0                <1> 	xor	eax, eax ; 0
  4426 00004CFB BF[986B0000]        <1> 	mov	edi, inode 
  4427 00004D00 F3AB                <1> 	rep	stosd
  4428                              <1> 	;
  4429 00004D02 668F05[986B0000]    <1> 	pop	word [i.flgs] ; * ; 24/12/2021
  4430                              <1> 		; mov (sp)+,i.flgs / fill flags
  4431 00004D09 8A0D[E46E0000]      <1> 	mov 	cl, [u.uid] ; 02/08/2013
  4432 00004D0F 880D[9B6B0000]      <1> 	mov 	[i.uid], cl
  4433                              <1> 		; movb u.uid,i.uid / user id	
  4434 00004D15 C605[9A6B0000]01    <1> 	mov     byte [i.nlks], 1
  4435                              <1> 		; movb $1,i.nlks / 1 link
  4436                              <1> 	;call	epoch ; Retro UNIX 8086 v1 modification !
  4437                              <1> 	;mov	eax, [s.time]
  4438                              <1> 	;mov 	[i.ctim], eax
  4439                              <1> 	 	; mov s.time,i.ctim / time created
  4440                              <1> 	 	; mov s.time+2,i.ctim+2 / time modified
  4441                              <1> 	; Retro UNIX 8086 v1 modification !
  4442                              <1> 	; i.ctime=0, i.ctime+2=0 and
  4443                              <1>         ; 'setimod' will set ctime of file via 'epoch'
  4444                              <1> 	;call	setimod
  4445                              <1> 	;	; jsr r0,setimod / set modified flag
  4446                              <1> 	;retn
  4447                              <1> 	;	; rts r0 / return
  4448                              <1> 	; 24/12/2021
  4449 00004D1C E983050000          <1> 	jmp	setimod
  4450                              <1> 
  4451                              <1> sysseek: ; / moves read write pointer in an fsp entry
  4452                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4453                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4454                              <1> 	;
  4455                              <1> 	; 'sysseek' changes the r/w pointer of (3rd word of in an
  4456                              <1> 	; fsp entry) of an open file whose file descriptor is in u.r0.
  4457                              <1> 	; The file descriptor refers to a file open for reading or
  4458                              <1> 	; writing. The read (or write) pointer is set as follows:
  4459                              <1> 	;	* if 'ptrname' is 0, the pointer is set to offset.
  4460                              <1> 	;	* if 'ptrname' is 1, the pointer is set to its
  4461                              <1> 	;	  current location plus offset.
  4462                              <1> 	;	* if 'ptrname' is 2, the pointer is set to the
  4463                              <1> 	;	  size of file plus offset.
  4464                              <1> 	; The error bit (e-bit) is set for an undefined descriptor.
  4465                              <1> 	;
  4466                              <1> 	; Calling sequence:
  4467                              <1> 	;	sysseek; offset; ptrname
  4468                              <1> 	; Arguments:
  4469                              <1> 	;	offset - number of bytes desired to move 
  4470                              <1> 	;		 the r/w pointer
  4471                              <1> 	;	ptrname - a switch indicated above
  4472                              <1> 	;
  4473                              <1> 	; Inputs: r0 - file descriptor 
  4474                              <1> 	; Outputs: -
  4475                              <1> 	; ...............................................................
  4476                              <1> 	;	
  4477                              <1> 	; Retro UNIX 8086 v1 modification: 
  4478                              <1> 	;       'sysseek' system call has three arguments; so,
  4479                              <1> 	;	* 1st argument, file descriptor is in BX (BL) register
  4480                              <1> 	;	* 2nd argument, offset is in CX register
  4481                              <1> 	;	* 3rd argument, ptrname/switch is in DX (DL) register	
  4482                              <1> 	;	
  4483                              <1> 
  4484 00004D21 E822000000          <1> 	call	seektell
  4485                              <1> 	; AX = u.count
  4486                              <1> 	; BX = *u.fofp
  4487                              <1> 		; jsr r0,seektell / get proper value in u.count
  4488                              <1> 		; add u.base,u.count / add u.base to it
  4489 00004D26 0305[B86E0000]      <1> 	add	eax, [u.base] ; add offset (u.base) to base
  4490 00004D2C 8903                <1> 	mov	[ebx], eax
  4491                              <1> 		; mov u.count,*u.fofp / put result into r/w pointer
  4492 00004D2E E9BFEDFFFF          <1> 	jmp	sysret
  4493                              <1> 		; br sysret4
  4494                              <1> 
  4495                              <1> systell: ; / get the r/w pointer
  4496                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  4497                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4498                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4499                              <1> 	;
  4500                              <1> 	; Retro UNIX 8086 v1 modification:
  4501                              <1> 	; ! 'systell' does not work in original UNIX v1,
  4502                              <1> 	; 	    it returns with error !
  4503                              <1> 	; Inputs: r0 - file descriptor 
  4504                              <1> 	; Outputs: r0 - file r/w pointer
  4505                              <1> 
  4506                              <1> 	;xor	ecx, ecx ; 0
  4507                              <1> 	;mov	edx, 1 ; 05/08/2013
  4508                              <1> 	; 24/12/2021
  4509 00004D33 29D2                <1> 	sub	edx, edx
  4510 00004D35 FEC2                <1> 	inc	dl
  4511                              <1> 	; edx = 1
  4512                              <1> 	;call 	seektell
  4513 00004D37 E812000000          <1> 	call 	seektell0 ; 05/08/2013
  4514                              <1> 	;mov	ebx, [u.fofp]
  4515 00004D3C 8B03                <1> 	mov	eax, [ebx]
  4516 00004D3E A3[986E0000]        <1> 	mov	[u.r0], eax
  4517 00004D43 E9AAEDFFFF          <1> 	jmp	sysret
  4518                              <1> 
  4519                              <1> ; Original unix v1 'systell' system call:
  4520                              <1> 		; jsr r0,seektell
  4521                              <1> 		; br error4
  4522                              <1> 
  4523                              <1> seektell:
  4524                              <1> 	; 03/02/2022
  4525                              <1> 	; 03/01/2016
  4526                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4527                              <1> 	; 07/07/2013 - 05/08/2013 (Retro UNIX 8086 v1)
  4528                              <1> 	;
  4529                              <1> 	; 'seektell' puts the arguments from sysseek and systell
  4530                              <1> 	; call in u.base and u.count. It then gets the i-number of
  4531                              <1> 	; the file from the file descriptor in u.r0 and by calling
  4532                              <1> 	; getf. The i-node is brought into core and then u.count
  4533                              <1> 	; is checked to see it is a 0, 1, or 2.
  4534                              <1> 	; If it is 0 - u.count stays the same
  4535                              <1> 	;          1 - u.count = offset (u.fofp)
  4536                              <1> 	;	   2 - u.count = i.size (size of file)
  4537                              <1> 	; 	 		
  4538                              <1> 	; !! Retro UNIX 8086 v1 modification:
  4539                              <1> 	;	Argument 1, file descriptor is in BX;
  4540                              <1> 	;	Argument 2, offset is in CX;
  4541                              <1> 	;	Argument 3, ptrname/switch is in DX register.	
  4542                              <1> 	;
  4543                              <1> 	; mov 	ax, 3 ; Argument transfer method 3 (three arguments)	
  4544                              <1> 	; call 	arg
  4545                              <1> 	;
  4546                              <1> 	; ((Return -> ax = base for offset (position= base+offset))
  4547                              <1> 	;
  4548 00004D48 890D[B86E0000]      <1> 	mov 	[u.base], ecx ; offset
  4549                              <1> 		; jsr r0,arg; u.base / puts offset in u.base
  4550                              <1> seektell0:
  4551 00004D4E 8915[BC6E0000]      <1> 	mov 	[u.count], edx
  4552                              <1> 		; jsr r0,arg; u.count / put ptr name in u.count
  4553                              <1> 	; mov	ax, bx
  4554                              <1> 		; mov *u.r0,r1 / file descriptor in r1 
  4555                              <1> 			     ; / (index in u.fp list)
  4556                              <1> 	; call	getf
  4557                              <1> 		; jsr r0,getf / u.fofp points to 3rd word in fsp entry
  4558                              <1> 	; BX = file descriptor (file number)
  4559 00004D54 E846FCFFFF          <1> 	call	getf1
  4560                              <1> 	; 03/02/2022
  4561 00004D59 09C0                <1> 	or	eax, eax
  4562                              <1> 	;or	ax, ax ; i-number of the file
  4563                              <1> 		; mov r1,-(sp) / r1 has i-number of file, 
  4564                              <1> 		             ; / put it on the stack
  4565                              <1> 	;jz	error
  4566                              <1> 		; beq error4 / if i-number is 0, not active so error
  4567 00004D5B 750F                <1> 	jnz	short seektell1
  4568 00004D5D C705[ED6E0000]0A00- <1> 	mov	dword [u.error], ERR_FILE_NOT_OPEN  ; 'file not open !'
  4568 00004D65 0000                <1>
  4569 00004D67 E966EDFFFF          <1> 	jmp	error
  4570                              <1> seektell1:
  4571                              <1> 	;push	eax
  4572 00004D6C 80FC80              <1> 	cmp	ah, 80h
  4573 00004D6F 7203                <1> 	jb	short seektell2
  4574                              <1> 		; bgt .+4 / if its positive jump
  4575 00004D71 66F7D8              <1> 	neg	ax
  4576                              <1> 		; neg r1 / if not make it positive
  4577                              <1> seektell2:
  4578 00004D74 E821040000          <1> 	call	iget
  4579                              <1> 		; jsr r0,iget / get its i-node into core
  4580 00004D79 8B1D[A86E0000]      <1>         mov     ebx, [u.fofp] ; 05/08/2013
  4581 00004D7F 803D[BC6E0000]01    <1> 	cmp	byte [u.count], 1
  4582                              <1> 		; cmp u.count,$1 / is ptr name =1
  4583 00004D86 7705                <1> 	ja	short seektell3
  4584                              <1> 		; blt 2f / no its zero
  4585 00004D88 740A                <1> 	je	short seektell_4
  4586                              <1> 		; beq 1f / yes its 1
  4587 00004D8A 31C0                <1> 	xor	eax, eax
  4588                              <1> 	;jmp	short seektell_5
  4589 00004D8C C3                  <1> 	retn
  4590                              <1> seektell3:
  4591                              <1> 	; 03/01/2016
  4592                              <1> 	;movzx	eax, word [i.size]
  4593 00004D8D 66A1[9C6B0000]      <1>         mov   	ax, [i.size]
  4594                              <1>                 ; mov i.size,u.count /  put number of bytes 
  4595                              <1>                                    ; / in file in u.count
  4596                              <1> 	;jmp	short seektell_5
  4597                              <1> 		; br 2f
  4598 00004D93 C3                  <1> 	retn
  4599                              <1> seektell_4: ; 1: / ptrname =1
  4600                              <1> 	;mov	ebx, [u.fofp]
  4601 00004D94 8B03                <1> 	mov	eax, [ebx]
  4602                              <1> 		; mov *u.fofp,u.count / put offset in u.count
  4603                              <1> ;seektell_5: ; 2: / ptrname =0
  4604                              <1> 	;mov	[u.count], eax
  4605                              <1> 	;pop	eax 
  4606                              <1> 		; mov (sp)+,r1 / i-number on stack  r1
  4607 00004D96 C3                  <1> 	retn
  4608                              <1> 		; rts r0
  4609                              <1> 
  4610                              <1> sysintr: ; / set interrupt handling
  4611                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4612                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4613                              <1> 	;
  4614                              <1> 	; 'sysintr' sets the interrupt handling value. It puts
  4615                              <1> 	; argument of its call in u.intr then branches into 'sysquit'
  4616                              <1> 	; routine. u.tty is checked if to see if a control tty exists.
  4617                              <1> 	; If one does the interrupt character in the tty buffer is
  4618                              <1> 	; cleared and 'sysret'is called. If one does not exits
  4619                              <1> 	; 'sysret' is just called.	
  4620                              <1> 	;
  4621                              <1> 	; Calling sequence:
  4622                              <1> 	;	sysintr; arg
  4623                              <1> 	; Argument:
  4624                              <1> 	;	arg - if 0, interrupts (ASCII DELETE) are ignored.
  4625                              <1> 	;	    - if 1, intterupts cause their normal result
  4626                              <1> 	;		 i.e force an exit.
  4627                              <1> 	;	    - if arg is a location within the program,
  4628                              <1> 	;		control is passed to that location when
  4629                              <1> 	;		an interrupt occurs.	
  4630                              <1> 	; Inputs: -
  4631                              <1> 	; Outputs: -
  4632                              <1> 	; ...............................................................
  4633                              <1> 	;	
  4634                              <1> 	; Retro UNIX 8086 v1 modification: 
  4635                              <1> 	;       'sysintr' system call sets u.intr to value of BX
  4636                              <1> 	;	then branches into sysquit.
  4637                              <1> 	;
  4638 00004D97 66891D[DC6E0000]    <1> 	mov	[u.intr], bx
  4639                              <1> 		; jsr r0,arg; u.intr / put the argument in u.intr
  4640                              <1> 		; br 1f / go into quit routine
  4641 00004D9E E94FEDFFFF          <1> 	jmp	sysret
  4642                              <1> 
  4643                              <1> sysquit:
  4644                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4645                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4646                              <1> 	;
  4647                              <1> 	; 'sysquit' turns off the quit signal. it puts the argument of
  4648                              <1> 	; the call in u.quit. u.tty is checked if to see if a control 
  4649                              <1> 	; tty exists. If one does the interrupt character in the tty
  4650                              <1> 	; buffer is cleared and 'sysret'is called. If one does not exits
  4651                              <1> 	; 'sysret' is just called.	
  4652                              <1> 	;
  4653                              <1> 	; Calling sequence:
  4654                              <1> 	;	sysquit; arg
  4655                              <1> 	; Argument:
  4656                              <1> 	;	arg - if 0, this call diables quit signals from the
  4657                              <1> 	;		typewriter (ASCII FS)
  4658                              <1> 	;	    - if 1, quits are re-enabled and cause execution to
  4659                              <1> 	;		cease and a core image to be produced.
  4660                              <1> 	;		 i.e force an exit.
  4661                              <1> 	;	    - if arg is an addres in the program,
  4662                              <1> 	;		a quit causes control to sent to that
  4663                              <1> 	;		location.	
  4664                              <1> 	; Inputs: -
  4665                              <1> 	; Outputs: -
  4666                              <1> 	; ...............................................................
  4667                              <1> 	;	
  4668                              <1> 	; Retro UNIX 8086 v1 modification: 
  4669                              <1> 	;       'sysquit' system call sets u.quit to value of BX
  4670                              <1> 	;	then branches into 'sysret'.
  4671                              <1> 	;
  4672 00004DA3 66891D[DE6E0000]    <1> 	mov	[u.quit], bx
  4673 00004DAA E943EDFFFF          <1> 	jmp	sysret
  4674                              <1> 		; jsr r0,arg; u.quit / put argument in u.quit
  4675                              <1> 	;1:
  4676                              <1> 		; mov u.ttyp,r1 / move pointer to control tty buffer
  4677                              <1> 			      ; / to r1
  4678                              <1> 		; beq sysret4 / return to user
  4679                              <1> 		; clrb 6(r1) / clear the interrupt character 
  4680                              <1> 			   ; / in the tty buffer
  4681                              <1> 		; br sysret4 / return to user
  4682                              <1> 
  4683                              <1> syssetuid: ; / set process id
  4684                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4685                              <1> 	; 07/07/2013 - 02/08/2013 (Retro UNIX 8086 v1)
  4686                              <1> 	;
  4687                              <1> 	; 'syssetuid' sets the user id (u.uid) of the current process
  4688                              <1> 	; to the process id in (u.r0). Both the effective user and 
  4689                              <1> 	; u.uid and the real user u.ruid are set to this. 
  4690                              <1> 	; Only the super user can make this call.	
  4691                              <1> 	;
  4692                              <1> 	; Calling sequence:
  4693                              <1> 	;	syssetuid
  4694                              <1> 	; Arguments: -
  4695                              <1> 	;
  4696                              <1> 	; Inputs: (u.r0) - contains the process id.
  4697                              <1> 	; Outputs: -
  4698                              <1> 	; ...............................................................
  4699                              <1> 	;	
  4700                              <1> 	; Retro UNIX 8086 v1 modification: 
  4701                              <1> 	;       BL contains the (new) user ID of the current process
  4702                              <1> 
  4703                              <1> 		; movb *u.r0,r1 / move process id (number) to r1
  4704 00004DAF 3A1D[E56E0000]      <1> 	cmp	bl, [u.ruid] 
  4705                              <1> 		; cmpb r1,u.ruid / is it equal to the real user 
  4706                              <1> 			       ; / id number
  4707 00004DB5 741E                <1> 	je	short setuid1
  4708                              <1> 		; beq 1f / yes
  4709 00004DB7 803D[E46E0000]00    <1> 	cmp	byte [u.uid], 0 ; 02/08/2013
  4710                              <1> 		; tstb u.uid / no, is current user the super user?
  4711                              <1> 	;ja	error
  4712                              <1> 		; bne error4 / no, error
  4713 00004DBE 760F                <1> 	jna	short setuid0
  4714 00004DC0 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_NOT_SUPERUSER  ; 11
  4714 00004DC8 0000                <1>
  4715                              <1> 				; 'permission denied !' error
  4716 00004DCA E903EDFFFF          <1> 	jmp	error
  4717                              <1> setuid0:
  4718 00004DCF 881D[E56E0000]      <1> 	mov	[u.ruid], bl
  4719                              <1> setuid1: ; 1:
  4720 00004DD5 881D[E46E0000]      <1> 	mov	[u.uid], bl ; 02/08/2013
  4721                              <1> 		; movb r1,u.uid / put process id in u.uid
  4722                              <1> 		; movb r1,u.ruid / put process id in u.ruid
  4723 00004DDB E912EDFFFF          <1> 	jmp	sysret
  4724                              <1> 		; br sysret4 / system return
  4725                              <1> 
  4726                              <1> sysgetuid: ; < get user id >
  4727                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  4728                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4729                              <1> 	; 07/07/2013 (Retro UNIX 8086 v1)
  4730                              <1> 	;
  4731                              <1> 	; 'sysgetuid' returns the real user ID of the current process.
  4732                              <1> 	; The real user ID identifies the person who is logged in,
  4733                              <1> 	; in contradistinction to the effective user ID, which
  4734                              <1> 	; determines his access permission at each moment. It is thus
  4735                              <1> 	; useful to programs which operate using the 'set user ID'
  4736                              <1> 	; mode, to find out who invoked them.	
  4737                              <1> 	;
  4738                              <1> 	; Calling sequence:
  4739                              <1> 	;	syssetuid
  4740                              <1> 	; Arguments: -
  4741                              <1> 	;
  4742                              <1> 	; Inputs: -
  4743                              <1> 	; Outputs: (u.r0) - contains the real user's id.
  4744                              <1> 	; ...............................................................
  4745                              <1> 	;	
  4746                              <1> 	; Retro UNIX 8086 v1 modification: 
  4747                              <1> 	;       AL contains the real user ID at return.
  4748                              <1> 	;
  4749                              <1> 	;movzx 	eax, byte [u.ruid]
  4750                              <1> 	; 09/01/2022
  4751 00004DE0 A0[E56E0000]        <1> 	mov	al, [u.ruid]
  4752 00004DE5 A3[986E0000]        <1> 	mov	[u.r0], eax
  4753                              <1> 		; movb	u.ruid,*u.r0 / move the real user id to (u.r0)
  4754 00004DEA E903EDFFFF          <1> 	jmp	sysret
  4755                              <1> 		; br sysret4 / systerm return, sysret
  4756                              <1> 
  4757                              <1> anyi: 
  4758                              <1> 	; 22/06/2015 (Retro UNIX 386 v1 - Beginning)
  4759                              <1> 	; 25/04/2013 (Retro UNIX 8086 v1)
  4760                              <1> 	;
  4761                              <1> 	; 'anyi' is called if a file deleted while open.
  4762                              <1> 	; "anyi" checks to see if someone else has opened this file.
  4763                              <1> 	;
  4764                              <1> 	; INPUTS ->
  4765                              <1> 	;    r1 - contains an i-number
  4766                              <1> 	;    fsp - start of table containing open files
  4767                              <1> 	;
  4768                              <1> 	; OUTPUTS ->
  4769                              <1> 	;    "deleted" flag set in fsp entry of another occurrence of
  4770                              <1> 	;	   this file and r2 points 1st word of this fsp entry.
  4771                              <1> 	;    if file not found - bit in i-node map is cleared
  4772                              <1> 	;    			 (i-node is freed)
  4773                              <1> 	;               all blocks related to i-node are freed
  4774                              <1> 	;	        all flags in i-node are cleared
  4775                              <1> 	; ((AX = R1)) input
  4776                              <1> 	;
  4777                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  4778                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  4779                              <1> 	;
  4780                              <1> 		; / r1 contains an i-number
  4781 00004DEF BB[686C0000]        <1> 	mov	ebx, fsp
  4782                              <1> 		; mov $fsp,r2 / move start of fsp table to r2
  4783                              <1> anyi_1: ; 1:
  4784 00004DF4 663B03              <1> 	cmp	ax, [ebx]
  4785                              <1> 		; cmp r1,(r2) / do i-numbers match?
  4786 00004DF7 7433                <1> 	je	short anyi_3
  4787                              <1> 		; beq 1f / yes, 1f
  4788 00004DF9 66F7D8              <1> 	neg	ax
  4789                              <1> 		; neg r1 / no complement r1
  4790 00004DFC 663B03              <1> 	cmp	ax, [ebx]
  4791                              <1> 		; cmp r1,(r2) / do they match now?
  4792 00004DFF 742B                <1> 	je	short anyi_3
  4793                              <1> 		; beq 1f / yes, transfer
  4794                              <1> 		; / i-numbers do not match
  4795 00004E01 83C30A              <1> 	add	ebx, 10 ; fsp table size is 10 bytes
  4796                              <1> 			; in Retro UNIX 386 v1 (22/06/2015)
  4797                              <1> 		; add $8,r2 / no, bump to next entry in fsp table
  4798 00004E04 81FB[5C6E0000]      <1> 	cmp	ebx, fsp + (nfiles*10) ; 22/06/2015 
  4799                              <1> 		; cmp r2,$fsp+[nfiles*8] 
  4800                              <1> 				; / are we at last entry in the table
  4801 00004E0A 72E8                <1> 	jb	short anyi_1
  4802                              <1> 		; blt 1b / no, check next entries i-number
  4803                              <1> 	;cmp	ax, 32768
  4804 00004E0C 80FC80              <1> 	cmp	ah, 80h ; negative number check
  4805                              <1> 		; tst r1 / yes, no match
  4806                              <1> 		; bge .+4
  4807 00004E0F 7203                <1> 	jb	short anyi_2
  4808 00004E11 66F7D8              <1> 	neg	ax
  4809                              <1> 		; neg r1 / make i-number positive
  4810                              <1> anyi_2:	
  4811 00004E14 E81A050000          <1> 	call	imap
  4812                              <1> 		; jsr r0,imap / get address of allocation bit 
  4813                              <1> 			    ; / in the i-map in r2
  4814                              <1> 	;; DL/DX (MQ) has a 1 in the calculated bit position
  4815                              <1>         ;; eBX (R2) has address of the byte with allocation bit
  4816                              <1>  	; not	dx
  4817 00004E19 F6D2                <1> 	not 	dl ;; 0 at calculated bit position, other bits are 1
  4818                              <1>         ;and	[ebx], dx
  4819 00004E1B 2013                <1> 	and 	[ebx], dl 
  4820                              <1> 		; bicb mq,(r2) / clear bit for i-node in the imap
  4821 00004E1D E8A4040000          <1> 	call	itrunc
  4822                              <1> 		; jsr r0,itrunc / free all blocks related to i-node
  4823 00004E22 66C705[986B0000]00- <1>  	mov 	word [i.flgs], 0
  4823 00004E2A 00                  <1>
  4824                              <1> 		; clr i.flgs / clear all flags in the i-node
  4825 00004E2B C3                  <1> 	retn
  4826                              <1> 		;rts	r0 / return
  4827                              <1> anyi_3: ; 1: / i-numbers match
  4828 00004E2C FE4309              <1> 	inc 	byte [ebx+9] ; 22/06/2015
  4829                              <1> 		;incb 7(r2) / increment upper byte of the 4th word
  4830                              <1> 		   ; / in that fsp entry (deleted flag of fsp entry)
  4831 00004E2F C3                  <1> 	retn
  4832                              <1> 		; rts r0
  2098                                  %include 'u3.s'        ; 10/05/2015
  2099                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.1) - SYS3.INC
  2100                              <1> ; Last Modification: 24/12/2021
  2101                              <1> ; ----------------------------------------------------------------------------
  2102                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2103                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2104                              <1> ;
  2105                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2106                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2107                              <1> ; <Bell Laboratories (17/3/1972)>
  2108                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2109                              <1> ;
  2110                              <1> ; Retro UNIX 8086 v1 - U3.ASM (08/03/2014) //// UNIX v1 -> u3.s
  2111                              <1> ;
  2112                              <1> ; ****************************************************************************
  2113                              <1> 
  2114                              <1> tswitch: ; Retro UNIX 386 v1
  2115                              <1> tswap:
  2116                              <1> 	; 01/09/2015
  2117                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2118                              <1> 	; 14/04/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2119                              <1> 	; time out swap, called when a user times out.
  2120                              <1> 	; the user is put on the low priority queue.
  2121                              <1> 	; This is done by making a link from the last user
  2122                              <1> 	; on the low priority queue to him via a call to 'putlu'.
  2123                              <1> 	; then he is swapped out.
  2124                              <1> 	;
  2125                              <1> 	; Retro UNIX 386 v1 modification ->
  2126                              <1> 	;       swap (software task switch) is performed by changing
  2127                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2128                              <1> 	;	as in Retro UNIX 8086 v1.
  2129                              <1> 	;
  2130                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2131                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2132                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2133                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2134                              <1> 	;	compatibles was using 1MB segmented memory 
  2135                              <1> 	;	in 8086/8088 times.
  2136                              <1> 	;
  2137                              <1> 	; INPUTS ->
  2138                              <1> 	;    u.uno - users process number
  2139                              <1> 	;    runq+4 - lowest priority queue
  2140                              <1> 	; OUTPUTS ->
  2141                              <1> 	;    r0 - users process number
  2142                              <1> 	;    r2 - lowest priority queue address
  2143                              <1> 	;
  2144                              <1> 	; ((AX = R0, BX = R2)) output
  2145                              <1> 	; ((Modified registers: EDX, EBX, ECX, ESI, EDI))  	
  2146                              <1> 	;
  2147 00004E30 A0[E76E0000]        <1> 	mov 	al, [u.uno]
  2148                              <1> 	       	; movb u.uno,r1 / move users process number to r1
  2149                              <1> 		; mov  $runq+4,r2 
  2150                              <1> 			; / move lowest priority queue address to r2
  2151 00004E35 E8CD000000          <1>         call 	putlu
  2152                              <1> 		; jsr r0,putlu / create link from last user on Q to 
  2153                              <1> 		             ; / u.uno's user
  2154                              <1> 
  2155                              <1> switch: ; Retro UNIX 386 v1
  2156                              <1> swap:
  2157                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.2)
  2158                              <1> 	; 02/09/2015
  2159                              <1> 	; 01/09/2015
  2160                              <1> 	; 31/08/2015
  2161                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2162                              <1> 	; 14/04/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2163                              <1> 	; 'swap' is routine that controls the swapping of processes
  2164                              <1> 	; in and out of core.
  2165                              <1> 	;
  2166                              <1> 	; Retro UNIX 386 v1 modification ->
  2167                              <1> 	;       swap (software task switch) is performed by changing
  2168                              <1> 	;	user's page directory (u.pgdir) instead of segment change
  2169                              <1> 	;	as in Retro UNIX 8086 v1.
  2170                              <1> 	;
  2171                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2172                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2173                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2174                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2175                              <1> 	;	compatibles was using 1MB segmented memory 
  2176                              <1> 	;	in 8086/8088 times.
  2177                              <1> 	;
  2178                              <1> 	; INPUTS ->
  2179                              <1> 	;    runq table - contains processes to run.
  2180                              <1> 	;    p.link - contains next process in line to be run.
  2181                              <1> 	;    u.uno - process number of process in core	
  2182                              <1> 	;    s.stack - swap stack used as an internal stack for swapping.	
  2183                              <1> 	; OUTPUTS ->
  2184                              <1> 	;    (original unix v1 -> present process to its disk block)
  2185                              <1> 	;    (original unix v1 -> new process into core -> 
  2186                              <1> 	;	   Retro Unix 8086 v1 -> segment registers changed 
  2187                              <1> 	;	   for new process)
  2188                              <1> 	;    u.quant = 3 (Time quantum for a process)
  2189                              <1> 	; 	((INT 1Ch count down speed -> 18.2 times per second)	 	
  2190                              <1> 	;    RETRO UNIX 8086 v1 will use INT 1Ch (18.2 times per second)
  2191                              <1> 	;	 for now, it will swap the process if there is not
  2192                              <1> 	;	 a keyboard event (keystroke) (Int 15h, function 4Fh)
  2193                              <1> 	;	 or will count down from 3 to 0 even if there is a
  2194                              <1> 	;        keyboard event locking due to repetitive key strokes.
  2195                              <1> 	;	 u.quant will be reset to 3 for RETRO UNIX 8086 v1.
  2196                              <1> 	;
  2197                              <1> 	;    u.pri -points to highest priority run Q.
  2198                              <1> 	;    r2 - points to the run queue.
  2199                              <1> 	;    r1 - contains new process number
  2200                              <1> 	;    r0 - points to place in routine or process that called
  2201                              <1> 	;	  swap all user parameters
  2202                              <1> 	;				
  2203                              <1> 	; ((Modified registers: EAX, EDX, EBX, ECX, ESI, EDI))  	
  2204                              <1> 	;
  2205                              <1> swap_0:
  2206                              <1> 		;mov $300,*$ps / processor priority = 6
  2207 00004E3A BE[8A6E0000]        <1> 	mov	esi, runq
  2208                              <1> 		; mov $runq,r2 / r2 points to runq table
  2209                              <1> swap_1: ; 1: / search runq table for highest priority process
  2210 00004E3F 668B06              <1> 	mov	ax, [esi]
  2211 00004E42 6621C0              <1> 	and 	ax, ax
  2212                              <1>        		; tst (r2)+ / are there any processes to run 
  2213                              <1> 			  ; / in this Q entry
  2214 00004E45 7507                <1> 	jnz	short swap_2
  2215                              <1>        		; bne 1f / yes, process 1f
  2216                              <1> 		; cmp r2,$runq+6 / if zero compare address 
  2217                              <1> 			       ; / to end of table
  2218                              <1> 		; bne 1b / if not at end, go back
  2219 00004E47 E8E0000000          <1> 	call	idle
  2220                              <1> 		; jsr r0,idle; s.idlet+2 / wait for interrupt; 
  2221                              <1> 				       ; / all queues are empty
  2222 00004E4C EBF1                <1> 	jmp	short swap_1
  2223                              <1> 		; br swap
  2224                              <1> swap_2: ; 1:
  2225 00004E4E 0FB6D8              <1> 	movzx	ebx, al ; 02/09/2015
  2226                              <1> 		; tst -(r2) / restore pointer to right Q entry
  2227                              <1>  		; mov r2,u.pri / set present user to this run queue
  2228                              <1> 	        ; movb (r2)+,r1 / move 1st process in queue to r1
  2229 00004E51 38E0                <1> 	cmp	al, ah
  2230                              <1> 		; cmpb r1,(r2)+ / is there only 1 process 
  2231                              <1> 			      ; / in this Q to be run
  2232 00004E53 740A                <1> 	je	short swap_3
  2233                              <1>        		; beq 1f / yes
  2234                              <1> 		; tst -(r2) / no, pt r2 back to this Q entry
  2235                              <1> 	;movzx	ebx, al
  2236 00004E55 8AA3[076C0000]      <1> 	mov	ah, [ebx+p.link-1] 
  2237 00004E5B 8826                <1>        	mov	[esi], ah
  2238                              <1> 		; movb p.link-1(r1),(r2) / move next process 
  2239                              <1> 				       ; / in line into run queue
  2240 00004E5D EB05                <1> 	jmp	short swap_4
  2241                              <1>        		; br 2f
  2242                              <1> swap_3: ; 1:
  2243                              <1> 	;xor	dx, dx
  2244                              <1> 	; 24/12/2021
  2245 00004E5F 31D2                <1> 	xor	edx, edx
  2246 00004E61 668916              <1> 	mov	[esi], dx
  2247                              <1> 		; clr -(r2) / zero the entry; no processes on the Q
  2248                              <1> swap_4: ; / write out core to appropriate disk area and read 
  2249                              <1>       ; / in new process if required
  2250                              <1>        		; clr *$ps / clear processor status
  2251 00004E64 8A25[E76E0000]      <1> 	mov 	ah, [u.uno]
  2252 00004E6A 38C4                <1> 	cmp	ah, al
  2253                              <1> 		; cmpb r1,u.uno / is this process the same as 
  2254                              <1> 			      ; / the process in core?
  2255 00004E6C 743B                <1>        	je	short swap_8
  2256                              <1>        		; beq 2f / yes, don't have to swap
  2257                              <1>        		; mov r0,-(sp) / no, write out core; save r0 
  2258                              <1> 			   ; / (address in routine that called swap)
  2259                              <1> 		; mov r1,-(sp) / put r1 (new process #) on the stack
  2260                              <1> 	; 01/09/2015
  2261                              <1> 	;mov	[u.usp], esp
  2262                              <1>        		; mov sp,u.usp / save stack pointer
  2263                              <1> 		; mov $sstack,sp / move swap stack pointer 
  2264                              <1> 			       ; / to the stack pointer
  2265 00004E6E 08E4                <1> 	or	ah, ah
  2266                              <1>        		; tstb u.uno / is the process # = 0
  2267 00004E70 740D                <1>        	jz	short swap_6 ; 'sysexit'
  2268                              <1> 		; beq 1f / yes, kill process by overwriting
  2269                              <1> 	; 02/09/2015
  2270 00004E72 8925[946E0000]      <1> 	mov	[u.usp], esp ; return address for 'syswait' & 'sleep'
  2271                              <1> 	;
  2272 00004E78 E834000000          <1> 	call	wswap
  2273                              <1> 		; jsr r0,wswap / write out core to disk
  2274                              <1> 	 ; 31/08/2015
  2275                              <1> 	;movzx	ebx, al ; New (running) process number
  2276 00004E7D EB1C                <1> 	jmp 	short swap_7
  2277                              <1> swap_6:
  2278                              <1> 	; 31/08/2015
  2279                              <1> 	; Deallocate memory pages belong to the process
  2280                              <1> 	; which is being terminated
  2281                              <1> 	; 14/05/2015 ('sysexit')
  2282                              <1>  	; Deallocate memory pages of the process
  2283                              <1> 	; (Retro UNIX 386 v1 modification !)
  2284                              <1> 	;
  2285                              <1> 	; movzx ebx, al
  2286 00004E7F 53                  <1> 	push	ebx
  2287 00004E80 A1[F16E0000]        <1> 	mov 	eax, [u.pgdir]  ; page directory of the process
  2288 00004E85 8B1D[F56E0000]      <1> 	mov	ebx, [u.ppgdir] ; page directory of the parent process
  2289 00004E8B E856E0FFFF          <1> 	call	deallocate_page_dir
  2290 00004E90 A1[E86E0000]        <1> 	mov	eax, [u.upage] ; 'user' structure page of the process
  2291 00004E95 E8E4E0FFFF          <1> 	call	deallocate_page
  2292 00004E9A 5B                  <1> 	pop	ebx
  2293                              <1> swap_7: ;1: 
  2294                              <1> 	; 02/09/2015
  2295                              <1> 	; 31/08/2015
  2296                              <1> 	; 14/05/2015
  2297 00004E9B C0E302              <1> 	shl	bl, 2 ; * 4 
  2298 00004E9E 8B83[246C0000]      <1> 	mov	eax, [ebx+p.upage-4] ; the 'u' page of the new process
  2299                              <1> 	;cli
  2300 00004EA4 E831000000          <1> 	call	rswap
  2301                              <1>  		; mov (sp)+,r1 / restore r1 to new process number
  2302                              <1> 		; jsr r0,rswap / read new process into core
  2303                              <1>        		; jsr r0,unpack / unpack the users stack from next
  2304                              <1> 			      ; / to his program to its normal
  2305                              <1> 	; 01/09/2015
  2306                              <1> 	;mov	esp, [u.usp]	
  2307                              <1> 		; mov u.usp,sp / location; restore stack pointer to
  2308                              <1> 			     ; / new process stack
  2309                              <1> 		; mov (sp)+,r0 / put address of where the process 
  2310                              <1> 			     ; / that just got swapped in, left off.,
  2311                              <1> 			     ; / i.e., transfer control to new process
  2312                              <1> 	;sti
  2313                              <1> swap_8: ;2:
  2314                              <1> 	; RETRO UNIX 8086 v1 modification !
  2315 00004EA9 C605[DA6E0000]04    <1> 	mov	byte [u.quant], time_count 
  2316                              <1> 		; movb $30.,uquant / initialize process time quantum
  2317 00004EB0 C3                  <1> 	retn
  2318                              <1> 		; rts r0 / return
  2319                              <1> 
  2320                              <1> wswap:  ; < swap out, swap to disk >
  2321                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2322                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2323                              <1> 	; 'wswap' writes out the process that is in core onto its 
  2324                              <1> 	; appropriate disk area.
  2325                              <1> 	;
  2326                              <1> 	; Retro UNIX 386 v1 modification ->
  2327                              <1> 	;       User (u) structure content and the user's register content
  2328                              <1> 	;	will be copied to the process's/user's UPAGE (a page for
  2329                              <1> 	;	saving 'u' structure and user registers for task switching).
  2330                              <1> 	;	u.usp - points to kernel stack address which contains
  2331                              <1> 	;		user's registers while entering system call.  
  2332                              <1> 	;	u.sp  - points to kernel stack address 
  2333                              <1> 	;		to return from system call -for IRET-.
  2334                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2335                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2336                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2337                              <1> 	;
  2338                              <1> 	; Retro UNIX 8086 v1 modification ->
  2339                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2340                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2341                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2342                              <1> 	;	compatibles was using 1MB segmented memory 
  2343                              <1> 	;	in 8086/8088 times.
  2344                              <1> 	;
  2345                              <1> 	; INPUTS ->
  2346                              <1> 	;    u.break - points to end of program
  2347                              <1> 	;    u.usp - stack pointer at the moment of swap
  2348                              <1> 	;    core - beginning of process program		
  2349                              <1> 	;    ecore - end of core 	
  2350                              <1> 	;    user - start of user parameter area		
  2351                              <1> 	;    u.uno - user process number	
  2352                              <1> 	;    p.dska - holds block number of process	
  2353                              <1> 	; OUTPUTS ->
  2354                              <1> 	;    swp I/O queue
  2355                              <1> 	;    p.break - negative word count of process 
  2356                              <1> 	;    r1 - process disk address	
  2357                              <1> 	;    r2 - negative word count
  2358                              <1> 	;
  2359                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2360                              <1> 	;
  2361                              <1> 	; INPUTS ->
  2362                              <1> 	;    u.uno - process number (to be swapped out)
  2363                              <1> 	; OUTPUTS ->
  2364                              <1> 	;    none
  2365                              <1> 	;
  2366                              <1> 	;   ((Modified registers: ECX, ESI, EDI))  
  2367                              <1> 	;
  2368 00004EB1 8B3D[E86E0000]      <1> 	mov	edi, [u.upage] ; process's user (u) structure page addr
  2369 00004EB7 B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2370 00004EBC BE[906E0000]        <1> 	mov	esi, user ; active user (u) structure	
  2371 00004EC1 F3A5                <1> 	rep	movsd
  2372                              <1> 	;
  2373 00004EC3 8B35[946E0000]      <1> 	mov	esi, [u.usp] ; esp (system stack pointer, 
  2374                              <1> 			     ;      points to user registers)
  2375 00004EC9 8B0D[906E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2376                              <1> 			     ; (for IRET)
  2377                              <1> 			     ; [u.sp] -> EIP (user)
  2378                              <1> 			     ; [u.sp+4]-> CS (user)
  2379                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2380                              <1> 			     ; [u.sp+12] -> ESP (user)
  2381                              <1> 			     ; [u.sp+16] -> SS (user)	
  2382 00004ECF 29F1                <1> 	sub	ecx, esi     ; required space for user registers
  2383 00004ED1 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2384                              <1> 			     ; (for IRET) 	
  2385 00004ED4 C1E902              <1> 	shr	ecx, 2	     		
  2386 00004ED7 F3A5                <1> 	rep	movsd
  2387 00004ED9 C3                  <1> 	retn
  2388                              <1> 
  2389                              <1> 	; Original UNIX v1 'wswap' routine:
  2390                              <1> 	; wswap:
  2391                              <1> 		; mov *$30,u.emt / determines handling of emts
  2392                              <1>         	; mov *$10,u.ilgins / determines handling of 
  2393                              <1> 				; / illegal instructions
  2394                              <1> 		; mov u.break,r2 / put process program break address in r2
  2395                              <1> 		; inc r2 / add 1 to it 
  2396                              <1> 		; bic $1,r2 / make it even
  2397                              <1> 		; mov r2,u.break / set break to an even location
  2398                              <1> 		; mov u.usp,r3 / put users stack pointer 
  2399                              <1> 			     ; / at moment of swap in r3
  2400                              <1> 		; cmp r2,$core / is u.break less than $core
  2401                              <1> 		; blos 2f / yes
  2402                              <1> 		; cmp r2,r3 / no, is (u.break) greater than stack ptr.
  2403                              <1>        		; bhis 2f / yes
  2404                              <1> 	; 1:
  2405                              <1>        		; mov (r3)+,(r2)+ / no, pack stack next to users program
  2406                              <1> 		; cmp r3,$ecore / has stack reached end of core
  2407                              <1> 		; bne 1b / no, keep packing
  2408                              <1> 	 	; br 1f / yes
  2409                              <1> 	; 2:
  2410                              <1>        		; mov $ecore,r2 / put end of core in r2 
  2411                              <1> 	; 1:
  2412                              <1>        		; sub  $user,r2 / get number of bytes to write out 
  2413                              <1> 			   ; / (user up to end of stack gets written out)
  2414                              <1> 		; neg r2 / make it negative
  2415                              <1> 		; asr r2 / change bytes to words (divide by 2)
  2416                              <1> 		; mov r2,swp+4 / word count
  2417                              <1> 		; movb u.uno,r1 / move user process number to r1
  2418                              <1> 		; asl r1 / x2 for index
  2419                              <1>       		; mov r2,p.break-2(r1) / put negative of word count 
  2420                              <1> 				     ; / into the p.break table
  2421                              <1>        		; mov p.dska-2(r1),r1 / move disk address of swap area 
  2422                              <1> 				    ; /	for process to r1
  2423                              <1>        		; mov r1,swp+2 / put processes dska address in swp+2 
  2424                              <1> 			     ; / (block number)
  2425                              <1> 		; bis $1000,swp / set it up to write (set bit 9)
  2426                              <1>        		; jsr r0,ppoke / write process out on swap area of disk
  2427                              <1> 	; 1:
  2428                              <1>        		; tstb swp+1 / is lt done writing?
  2429                              <1>        		; bne 1b / no, wait
  2430                              <1> 		; rts r0 / yes, return to swap
  2431                              <1> 
  2432                              <1> rswap:  ; < swap in, swap from disk >
  2433                              <1> 	; 15/09/2015
  2434                              <1> 	; 28/08/2015
  2435                              <1> 	; 14/05/2015
  2436                              <1> 	; 09/05/2015 (Retro UNIX 386 v1 - Beginning)
  2437                              <1> 	; 26/05/2013 - 08/03/2014 (Retro UNIX 8086 v1)
  2438                              <1> 	; 'rswap' reads a process whose number is in r1, 
  2439                              <1> 	; from disk into core.
  2440                              <1> 	;
  2441                              <1> 	; Retro UNIX 386 v1 modification ->
  2442                              <1> 	;       User (u) structure content and the user's register content
  2443                              <1> 	;	will be restored from process's/user's UPAGE (a page for
  2444                              <1> 	;	saving 'u' structure and user registers for task switching).
  2445                              <1> 	;	u.usp - points to kernel stack address which contains
  2446                              <1> 	;		user's registers while entering system call.  
  2447                              <1> 	;	u.sp  - points to kernel stack address 
  2448                              <1> 	;		to return from system call -for IRET-.
  2449                              <1> 	;	[u.usp]+32+16 = [u.sp] 
  2450                              <1> 	;	[u.usp] -> edi, esi, ebp, esp (= [u.usp]+32), ebx, 
  2451                              <1> 	;		edx, ecx, eax, gs, fs, es, ds, -> [u.sp].
  2452                              <1> 	;
  2453                              <1> 	; RETRO UNIX 8086 v1 modification ->
  2454                              <1> 	;       'swap to disk' is replaced with 'change running segment'
  2455                              <1> 	;	according to 8086 cpu (x86 real mode) architecture.
  2456                              <1> 	;	pdp-11 was using 64KB uniform memory while IBM PC
  2457                              <1> 	;	compatibles was using 1MB segmented memory 
  2458                              <1> 	;	in 8086/8088 times.
  2459                              <1> 	;
  2460                              <1> 	; INPUTS ->
  2461                              <1> 	;    r1 - process number of process to be read in
  2462                              <1> 	;    p.break - negative of word count of process 
  2463                              <1> 	;    p.dska - disk address of the process		
  2464                              <1> 	;    u.emt - determines handling of emt's 	
  2465                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2466                              <1> 	; OUTPUTS ->
  2467                              <1> 	;    8 = (u.ilgins)
  2468                              <1> 	;    24 = (u.emt)
  2469                              <1> 	;    swp - bit 10 is set to indicate read 
  2470                              <1> 	;		(bit 15=0 when reading is done)	
  2471                              <1> 	;    swp+2 - disk block address
  2472                              <1> 	;    swp+4 - negative word count 	
  2473                              <1> 	;      ((swp+6 - address of user structure)) 
  2474                              <1> 	;
  2475                              <1> 	; RETRO UNIX 8086 v1 input/output:
  2476                              <1> 	;
  2477                              <1> 	; INPUTS ->
  2478                              <1> 	;    AL	- new process number (to be swapped in)	 
  2479                              <1> 	; OUTPUTS ->
  2480                              <1> 	;    none
  2481                              <1> 	;
  2482                              <1> 	;   ((Modified registers: EAX, ECX, ESI, EDI, ESP)) 
  2483                              <1> 	;
  2484                              <1> 	; Retro UNIX 386 v1 - modification ! 14/05/2015
  2485 00004EDA 89C6                <1> 	mov	esi, eax  ; process's user (u) structure page addr
  2486 00004EDC B91E000000          <1> 	mov	ecx, (U_SIZE + 3) / 4
  2487 00004EE1 BF[906E0000]        <1> 	mov	edi, user ; active user (u) structure	
  2488 00004EE6 F3A5                <1> 	rep	movsd
  2489 00004EE8 58                  <1> 	pop	eax ; 15/09/2015, 'rswap' return address 
  2490 00004EE9 8B3D[946E0000]      <1> 	mov	edi, [u.usp] ; esp (system stack pointer, 
  2491                              <1> 			     ;      points to user registers)
  2492 00004EEF 8B0D[906E0000]      <1> 	mov	ecx, [u.sp]  ; return address from the system call
  2493                              <1> 			     ; (for IRET)
  2494                              <1> 			     ; [u.sp] -> EIP (user)
  2495                              <1> 			     ; [u.sp+4]-> CS (user)
  2496                              <1> 			     ; [u.sp+8] -> EFLAGS (user)
  2497                              <1> 			     ; [u.sp+12] -> ESP (user)
  2498                              <1> 			     ; [u.sp+16] -> SS (user)		
  2499                              <1> 	; 28/08/2015
  2500 00004EF5 29F9                <1> 	sub	ecx, edi     ; required space for user registers
  2501 00004EF7 83C114              <1> 	add	ecx, 20	     ; +5 dwords to return from system call
  2502                              <1> 			     ; (for IRET) 	
  2503 00004EFA C1E902              <1> 	shr	ecx, 2	       		
  2504 00004EFD F3A5                <1> 	rep	movsd
  2505 00004EFF 8B25[946E0000]      <1> 	mov	esp, [u.usp] ; 15/09/2015
  2506 00004F05 50                  <1> 	push	eax ; 15/09/2015 'rswap' return address
  2507 00004F06 C3                  <1> 	retn
  2508                              <1> 
  2509                              <1> 	; Original UNIX v1 'rswap'  and 'unpack' routines:
  2510                              <1> 	;rswap:
  2511                              <1>        		; asl r1 / process number x2 for index
  2512                              <1>        		; mov p.break-2(r1), swp+4 / word count
  2513                              <1>        		; mov p.dska-2(r1),swp+2 / disk address
  2514                              <1>        		; bis $2000,swp / read
  2515                              <1>        		; jsr r0,ppoke / read it in 
  2516                              <1> 	; 1:
  2517                              <1>        		; tstb swp+1 / done
  2518                              <1>        		; bne 1b / no, wait for bit 15 to clear (inhibit bit)
  2519                              <1>        		; mov u.emt,*$30 / yes move these
  2520                              <1>        		; mov u.ilgins,*$10 / back
  2521                              <1>        		; rts r0 / return
  2522                              <1> 
  2523                              <1> 	;unpack: ; / move stack back to its normal place
  2524                              <1> 		; mov u.break,r2 / r2 points to end of user program
  2525                              <1>        		; cmp r2,$core / at beginning of user program yet?
  2526                              <1> 		; blos 2f / yes, return
  2527                              <1> 		; cmp r2,u.usp / is break_above the stack pointer 
  2528                              <1> 			     ; / before swapping
  2529                              <1> 		; bhis 2f / yes, return
  2530                              <1> 		; mov $ecore,r3 / r3 points to end of core
  2531                              <1> 		; add r3,r2
  2532                              <1> 		; sub u.usp,r2 / end of users stack is in r2
  2533                              <1> 	; 1:
  2534                              <1> 		; mov -(r2),-(r3) / move stack back to its normal place
  2535                              <1> 		; cmp r2,u.break / in core
  2536                              <1> 		; bne 1b
  2537                              <1> 	; 2:
  2538                              <1>        		; rts r0
  2539                              <1> 
  2540                              <1> putlu: 
  2541                              <1> 	; 12/09/2015
  2542                              <1> 	; 02/09/2015
  2543                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2544                              <1> 	; 15/04/2013 - 23/02/2014 (Retro UNIX 8086 v1)
  2545                              <1> 	; 'putlu' is called with a process number in r1 and a pointer
  2546                              <1> 	; to lowest priority Q (runq+4) in r2. A link is created from
  2547                              <1> 	; the last process on the queue to process in r1 by putting
  2548                              <1> 	; the process number in r1 into the last process's link.
  2549                              <1> 	;
  2550                              <1> 	; INPUTS ->
  2551                              <1> 	;    r1 - user process number
  2552                              <1> 	;    r2 - points to lowest priority queue 
  2553                              <1> 	;    p.dska - disk address of the process		
  2554                              <1> 	;    u.emt - determines handling of emt's 	
  2555                              <1> 	;    u.ilgins - determines handling of illegal instructions		
  2556                              <1> 	; OUTPUTS ->
  2557                              <1> 	;    r3 - process number of last process on the queue upon
  2558                              <1> 	;	  entering putlu
  2559                              <1> 	;    p.link-1 + r3 - process number in r1
  2560                              <1> 	;    r2 - points to lowest priority queue
  2561                              <1> 	;
  2562                              <1> 	; ((Modified registers: EDX, EBX)) 
  2563                              <1> 	;
  2564                              <1> 	; / r1 = user process no.; r2 points to lowest priority queue
  2565                              <1> 
  2566                              <1> 	; eBX = r2
  2567                              <1> 	; eAX = r1 (AL=r1b)
  2568                              <1> 
  2569 00004F07 BB[8A6E0000]        <1> 	mov	ebx, runq
  2570 00004F0C 0FB613              <1> 	movzx  	edx, byte [ebx]
  2571 00004F0F 43                  <1> 	inc	ebx
  2572 00004F10 20D2                <1> 	and	dl, dl
  2573                              <1> 		; tstb (r2)+ / is queue empty?
  2574 00004F12 740A                <1>        	jz	short putlu_1
  2575                              <1> 		; beq 1f / yes, branch
  2576 00004F14 8A13                <1> 	mov 	dl, [ebx] ; 12/09/2015
  2577                              <1> 		; movb (r2),r3 / no, save the "last user" process number
  2578                              <1> 			     ; / in r3
  2579 00004F16 8882[076C0000]      <1>        	mov	[edx+p.link-1], al
  2580                              <1> 		; movb r1,p.link-1(r3) / put pointer to user on 
  2581                              <1> 			     ; / "last users" link
  2582 00004F1C EB03                <1> 	jmp	short putlu_2
  2583                              <1> 		; br 2f /
  2584                              <1> putlu_1: ; 1:
  2585 00004F1E 8843FF              <1> 	mov	[ebx-1], al
  2586                              <1>        		; movb r1,-1(r2) / user is only user; 
  2587                              <1> 			    ; / put process no. at beginning and at end
  2588                              <1> putlu_2: ; 2: 
  2589 00004F21 8803                <1> 	mov	[ebx], al
  2590                              <1>        		; movb r1,(r2) / user process in r1 is now the last entry
  2591                              <1> 			     ; / on the queue
  2592 00004F23 88C2                <1> 	mov	dl, al
  2593 00004F25 88B2[076C0000]      <1>         mov     [edx+p.link-1], dh ; 0
  2594                              <1> 		; dec r2 / restore r2
  2595 00004F2B C3                  <1>         retn
  2596                              <1> 		; rts r0
  2597                              <1> 
  2598                              <1> ;copyz:
  2599                              <1> ;       mov     r1,-(sp) / put r1 on stack
  2600                              <1> ;       mov     r2,-(sp) / put r2 on stack
  2601                              <1> ;       mov     (r0)+,r1
  2602                              <1> ;       mov     (r0)+,r2
  2603                              <1> ;1:
  2604                              <1> ;       clr     (r1)+ / clear all locations between r1 and r2
  2605                              <1> ;       cmp     r1,r2 
  2606                              <1> ;       blo     1b
  2607                              <1> ;       mov     (sp)+,r2 / restore r2
  2608                              <1> ;       mov     (sp)+,r1 / restore r1
  2609                              <1> ;       rts     r0 
  2610                              <1> 
  2611                              <1> idle:
  2612                              <1> 	; 01/09/2015
  2613                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2614                              <1> 	; 10/04/2013 - 23/10/2013 (Retro UNIX 8086 v1)
  2615                              <1> 	; (idle & wait loop)
  2616                              <1> 	; Retro Unix 8086 v1 modification on original UNIX v1
  2617                              <1> 	; idle procedure!
  2618                              <1>       	;
  2619                              <1>   	; 01/09/2015
  2620 00004F2C FB                  <1> 	sti
  2621                              <1>       	; 29/07/2013
  2622 00004F2D F4                  <1>       	hlt
  2623 00004F2E 90                  <1>       	nop ; 10/10/2013
  2624 00004F2F 90                  <1>       	nop
  2625 00004F30 90                  <1>       	nop
  2626                              <1>       	; 23/10/2013
  2627 00004F31 90                  <1>       	nop
  2628 00004F32 90                  <1>       	nop
  2629 00004F33 90                  <1>       	nop
  2630 00004F34 90                  <1>       	nop
  2631 00004F35 C3                  <1>       	retn      
  2632                              <1> 
  2633                              <1> 	;mov *$ps,-(sp) / save ps on stack
  2634                              <1> 	;clr *$ps / clear ps
  2635                              <1> 	;mov clockp,-(sp) / save clockp on stack
  2636                              <1> 	;mov (r0)+,clockp / arg to idle in clockp
  2637                              <1> 	;1 / wait for interrupt
  2638                              <1> 	;mov (sp)+,clockp / restore clockp, ps
  2639                              <1> 	;mov (sp)+,*$ps
  2640                              <1> 	;rts r0
  2641                              <1> 
  2642                              <1> clear:
  2643                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2644                              <1> 	; 10/05/2015 (Retro UNIX 386 v1 - Beginning)
  2645                              <1> 	; 09/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2646                              <1> 	; 'clear' zero's out of a block (whose block number is in r1)
  2647                              <1> 	; on the current device (cdev)
  2648                              <1> 	;	
  2649                              <1> 	; INPUTS ->
  2650                              <1> 	;    r1 - block number of block to be zeroed
  2651                              <1> 	;    cdev - current device number 
  2652                              <1> 	; OUTPUTS ->
  2653                              <1> 	;    a zeroed I/O buffer onto the current device
  2654                              <1> 	;    r1 - points to last entry in the I/O buffer
  2655                              <1> 	;
  2656                              <1> 	; ((AX = R1)) input/output
  2657                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 14/11/2012, UNIXCOPY.ASM)
  2658                              <1>         ;    ((Modified registers: EDX, ECX, EBX, ESI, EDI, EBP))  
  2659                              <1> 
  2660 00004F36 E8AD0D0000          <1> 	call 	wslot
  2661                              <1> 		; jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
  2662                              <1>                    ; / word of I/O queue r5 points to first data word in buffer
  2663 00004F3B 89DF                <1> 	mov	edi, ebx ; r5
  2664 00004F3D 89C2                <1> 	mov	edx, eax
  2665 00004F3F B980000000          <1> 	mov	ecx, 128
  2666                              <1> 		; mov $256.,r3
  2667 00004F44 31C0                <1> 	xor	eax, eax
  2668 00004F46 F3AB                <1> 	rep	stosd
  2669 00004F48 89D0                <1> 	mov	eax, edx
  2670                              <1> ; 1: 
  2671                              <1>        		; clr (r5)+ / zero data word in buffer
  2672                              <1>        		; dec r3
  2673                              <1>        		; bgt 1b / branch until all data words in buffer are zero
  2674                              <1> 	;call	dskwr
  2675                              <1> 		; jsr r0,dskwr / write zeroed buffer area out onto physical
  2676                              <1>                              ; / block specified in r1
  2677                              <1> 	; eAX (r1) = block number
  2678                              <1> 	;retn
  2679                              <1> 		; rts r0
  2680                              <1> 	; 24/12/2021
  2681 00004F4A E9B50D0000          <1> 	jmp	dskwr
  2099                                  %include 'u4.s'        ; 15/04/2015
  2100                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS4.INC
  2101                              <1> ; Last Modification: 26/02/2022
  2102                              <1> ; ----------------------------------------------------------------------------
  2103                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2104                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2105                              <1> ;
  2106                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2107                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2108                              <1> ; <Bell Laboratories (17/3/1972)>
  2109                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2110                              <1> ;
  2111                              <1> ; Retro UNIX 8086 v1 - U4.ASM (04/07/2014) //// UNIX v1 -> u4.s
  2112                              <1> ;
  2113                              <1> ; ****************************************************************************
  2114                              <1> 
  2115                              <1> ;setisp:
  2116                              <1>        ;mov     r1,-(sp)
  2117                              <1>        ;mov     r2,-(sp)
  2118                              <1>        ;mov     r3,-(sp)
  2119                              <1>        ;mov     clockp,-(sp)
  2120                              <1>        ;mov     $s.syst+2,clockp
  2121                              <1>        ;jmp     (r0)
  2122                              <1> 
  2123                              <1> clock: ; / interrupt from 60 cycle clock
  2124                              <1> 	
  2125                              <1> 	; 14/10/2015
  2126                              <1> 	; 14/05/2015 (Retro UNIX 386 v1 - Beginning)
  2127                              <1> 	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)
  2128                              <1> 
  2129                              <1>        ;mov     r0,-(sp) / save r0
  2130                              <1>        ;tst     *$lks / restart clock?
  2131                              <1>        ;mov     $s.time+2,r0 / increment the time of day
  2132                              <1>        ;inc     (r0)
  2133                              <1>        ;bne     1f
  2134                              <1>        ;inc     -(r0)
  2135                              <1> ;1:
  2136                              <1>        ;mov     clockp,r0 / increment appropriate time category
  2137                              <1>        ;inc     (r0)
  2138                              <1>        ;bne     1f
  2139                              <1>        ;inc     -(r0)
  2140                              <1> ;1:
  2141                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2142                              <1> 
  2143 00004F4F 803D[DA6E0000]00    <1> 	cmp	byte [u.quant], 0
  2144 00004F56 772C                <1> 	ja	short clk_1
  2145                              <1> 	;
  2146 00004F58 803D[8F6E0000]FF    <1>         cmp     byte [sysflg], 0FFh ; user or system space ?
  2147 00004F5F 7529                <1> 	jne	short clk_2 ; system space (sysflg <> 0FFh)
  2148 00004F61 803D[E76E0000]01    <1> 	cmp     byte [u.uno], 1 ; /etc/init ?
  2149 00004F68 761A                <1> 	jna	short clk_1 ; yes, do not swap out
  2150 00004F6A 66833D[DC6E0000]00  <1> 	cmp	word [u.intr], 0
  2151 00004F72 7616                <1> 	jna	short clk_2
  2152                              <1> clk_0:
  2153                              <1> 	; 14/10/2015
  2154 00004F74 FE05[8F6E0000]      <1> 	inc	byte [sysflg] 	; Now, we are in system space
  2155 00004F7A 58                  <1> 	pop	eax ; return address to the timer interrupt
  2156                              <1> 	;
  2157 00004F7B B020                <1> 	MOV	AL,EOI			; GET END OF INTERRUPT MASK
  2158                              <1> 	;CLI				; DISABLE INTERRUPTS TILL STACK CLEARED
  2159 00004F7D E620                <1> 	OUT	INTA00,AL		; END OF INTERRUPT TO 8259 - 1	
  2160                              <1> 	;
  2161 00004F7F E9D3EBFFFF          <1> 	jmp     sysrelease ; 'sys release' by clock/timer
  2162                              <1> clk_1:
  2163 00004F84 FE0D[DA6E0000]      <1> 	dec	byte [u.quant]
  2164                              <1> clk_2:
  2165 00004F8A C3                  <1> 	retn   ; return to (hardware) timer interrupt routine
  2166                              <1> 
  2167                              <1> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
  2168                              <1> 
  2169                              <1>        ;mov     $uquant,r0 / decrement user time quantum
  2170                              <1>        ;decb    (r0)
  2171                              <1>        ;bge     1f / if less than 0
  2172                              <1>        ;clrb    (r0) / make it 0
  2173                              <1> ;1: / decrement time out counts return now if priority was not 0
  2174                              <1>        ;cmp     4(sp),$200 / ps greater than or equal to 200
  2175                              <1>        ;bge     2f / yes, check time outs
  2176                              <1>        ;tstb    (r0) / no, user timed out?
  2177                              <1>        ;bne     1f / no
  2178                              <1>        ;cmpb    sysflg,$-1 / yes, are we outside the system?
  2179                              <1>        ;bne     1f / no, 1f
  2180                              <1>        ;mov     (sp)+,r0 / yes, put users r0 in r0
  2181                              <1>        ;sys     0 / sysrele
  2182                              <1>        ;rti
  2183                              <1> ;2: / priority is high so just decrement time out counts
  2184                              <1>        ;mov     $toutt,r0 / r0 points to beginning of time out table
  2185                              <1> ;2:
  2186                              <1>        ;tstb    (r0) / is the time out?
  2187                              <1>        ;beq     3f / yes, 3f (get next entry)
  2188                              <1>        ;decb    (r0) / no, decrement the time
  2189                              <1>        ;bne     3f / isit zero now?
  2190                              <1>        ;incb    (r0) / yes, increment the time
  2191                              <1> ;3:
  2192                              <1>        ;inc     r0 / next entry
  2193                              <1>        ;cmp     r0,$touts / end of toutt table?
  2194                              <1>        ;blo     2b / no, check this entry
  2195                              <1>        ;mov     (sp)+,r0 / yes, restore r0
  2196                              <1>        ;rti / return from interrupt
  2197                              <1> ;1: / decrement time out counts; if 0 call subroutine
  2198                              <1>        ;mov     (sp)+,r0 / restore r0
  2199                              <1>        ;mov     $240,*$ps / set processor priority to 5
  2200                              <1>        ;jsr     r0,setisp / save registers
  2201                              <1>        ;mov     $touts-toutt-1,r0 / set up r0 as index to decrement thru
  2202                              <1>                                ;  / the table
  2203                              <1> ;1:
  2204                              <1>        ;tstb    toutt(r0) / is the time out for this entry
  2205                              <1>        ;beq     2f / yes
  2206                              <1>        ;decb    toutt(r0) / no, decrement the time
  2207                              <1>        ;bne     2f / is the time 0, now
  2208                              <1>        ;asl     r0 / yes, 2 x r0 to get word index for tout entry
  2209                              <1>        ;jsr     r0,*touts(r0) / go to appropriate routine specified in this
  2210                              <1>        ;asr     r0 / touts entry; set r0 back to toutt index
  2211                              <1> ;2:
  2212                              <1>        ;dec     r0 / set up r0 for next entry
  2213                              <1>        ;bge     1b / finished? , no, go back
  2214                              <1>        ;br      retisp / yes, restore registers and do a rti
  2215                              <1> 
  2216                              <1> ;retisp:
  2217                              <1>        ;mov     (sp)+,clockp / pop values before interrupt off the stack
  2218                              <1>        ;mov     (sp)+,r3
  2219                              <1>        ;mov     (sp)+,r2
  2220                              <1>        ;mov     (sp)+,r1
  2221                              <1>        ;mov     (sp)+,r0
  2222                              <1>        ;rti     / return from interrupt
  2223                              <1> 
  2224                              <1> 
  2225                              <1> wakeup: ; / wakeup processes waiting for an event 
  2226                              <1> 	; / by linking them to the queue
  2227                              <1> 	;
  2228                              <1> 	; 26/02/2022
  2229                              <1> 	; 15/09/2015
  2230                              <1> 	; 29/06/2015
  2231                              <1> 	; 15/04/2015 (Retro UNIX 386 v1 - Beginning)
  2232                              <1> 	;
  2233                              <1> 	; 15/05/2013 - 02/06/2014
  2234                              <1> 	; Retro UNIX 8086 v1 modification !
  2235                              <1> 	; (Process/task switching routine by using
  2236                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.)
  2237                              <1> 	;
  2238                              <1> 	; In original UNIX v1, 'wakeup' is called to wake the process
  2239                              <1> 	; sleeping in the specified wait channel by creating a link 
  2240                              <1> 	; to it from the last user process on the run queue.
  2241                              <1> 	; If there is no process to wake up, nothing happens.
  2242                              <1> 	;
  2243                              <1> 	; In Retro UNIX 8086 v1, Int 09h keyboard interrupt will set
  2244                              <1> 	; 'switching' status of the current process (owns current tty)
  2245                              <1> 	; (via alt + function keys) to a process which has highest
  2246                              <1> 	; priority (on run queue) on the requested tty (0 to 7, except
  2247                              <1> 	; 8 and 9 which are tty identifiers of COM1, COM2 serial ports)
  2248                              <1> 	; as it's console tty. (NOTE: 'p.ttyc' is used to set console
  2249                              <1> 	; tty for tty switching by keyboard.)	 
  2250                              <1> 	; 
  2251                              <1> 	; INPUT -> 
  2252                              <1> 	;	   AL = wait channel (r3) ('tty number' for now)
  2253                              <1> 	;	   ;;EBX = Run queue (r2) offset
  2254                              <1> 	;
  2255                              <1> 	; ((modified registers: EAX, EBX))
  2256                              <1> 	;
  2257 00004F8B 0FB6D8              <1> 	movzx	ebx, al ; 29/06/2015
  2258 00004F8E 81C3[386B0000]      <1> 	add	ebx, wlist
  2259 00004F94 8A03                <1> 	mov	al, [ebx] ; waiting list (waiting process number)
  2260 00004F96 20C0                <1> 	and	al, al
  2261 00004F98 741E                <1> 	jz	short wa0 ; nothing to wakeup
  2262                              <1> 	;
  2263 00004F9A 30E4                <1> 	xor	ah, ah
  2264 00004F9C 8825[DA6E0000]      <1> 	mov 	[u.quant], ah ; 0 ; time quantum = 0	
  2265 00004FA2 8823                <1> 	mov	[ebx], ah ; 0 ; zero wait channel entry
  2266                              <1> 	; 15/09/2015
  2267 00004FA4 0FB6D8              <1> 	movzx	ebx, al
  2268                              <1> 	; 26/02/2022 (p.waitc is not used)
  2269                              <1> 	;mov	[ebx+p.waitc-1], ah ; 0
  2270 00004FA7 FEC4                <1> 	inc	ah
  2271 00004FA9 88A3[176C0000]      <1> 	mov	byte [ebx+p.stat-1], ah ; 1 ; SRUN
  2272                              <1> 	;
  2273 00004FAF 57                  <1> 	push	edi
  2274 00004FB0 52                  <1> 	push	edx
  2275 00004FB1 E851FFFFFF          <1> 	call	putlu
  2276 00004FB6 5A                  <1> 	pop	edx
  2277 00004FB7 5F                  <1> 	pop	edi
  2278                              <1> wa0:
  2279 00004FB8 C3                  <1> 	retn
  2280                              <1> 
  2281                              <1> sleep: 
  2282                              <1> 	; 26/02/2022
  2283                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2284                              <1> 	; 15/09/2015
  2285                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2286                              <1> 	;
  2287                              <1> 	; 09/05/2013 - 20/03/2014
  2288                              <1> 	;
  2289                              <1> 	; Retro UNIX 8086 v1 modification !
  2290                              <1> 	; (Process/task switching and quit routine by using
  2291                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2292                              <1> 	;
  2293                              <1> 	; In original UNIX v1, 'sleep' is called to wait for
  2294                              <1> 	; tty and tape output or input becomes available
  2295                              <1> 	; and process is put on waiting channel and swapped out,
  2296                              <1> 	; then -when the tty or tape is ready to write or read-
  2297                              <1> 	; 'wakeup' gets process back to active swapped-in status.)
  2298                              <1> 	;
  2299                              <1> 	; In Retro UNIX 8086 v1, Int 1Bh ctrl+brk interrupt and
  2300                              <1> 	; Int 09h keyboard interrupt will set 'quit' or 'switching'		
  2301                              <1> 	; status of the current process also INT 1Ch will count down
  2302                              <1> 	; 'uquant' value and INT 09h will redirect scancode of keystroke
  2303                              <1> 	; to tty buffer of the current process and kernel will get
  2304                              <1> 	; user input by using tty buffer of the current process
  2305                              <1> 	; (instead of standard INT 16h interrupt).
  2306                              <1> 	; TTY output will be redirected to related video page of text mode
  2307                              <1> 	; (INT 10h will be called with different video page depending
  2308                              <1> 	; on tty assignment of the active process: 0 to 7 for
  2309                              <1> 	; pseudo screens.)
  2310                              <1> 	;
  2311                              <1> 	; In Retro UNIX 8086 v1, 'sleep' will be called to wait for
  2312                              <1> 	; a keystroke from keyboard or wait for reading or writing
  2313                              <1> 	; characters/data on serial port(s).
  2314                              <1> 	;
  2315                              <1> 	; Character/Terminal input/output through COM1 and COM2 will be
  2316                              <1> 	; performed by related routines in addition to pseudo TTY routines.
  2317                              <1> 	; 
  2318                              <1> 	; R1 = AH = wait channel (0-9 for TTYs) ; 05/10/2013 (22/09/2013)
  2319                              <1> 	;
  2320                              <1> 	;; 05/10/2013
  2321                              <1>         ;10/12/2013
  2322                              <1> 	;cmp   byte [u.uno], 1
  2323                              <1>         ;ja    short sleep0
  2324                              <1> 	;retn
  2325                              <1> 
  2326                              <1> 	; 20/03/2014
  2327                              <1> 	;mov	bx, [runq]
  2328                              <1> 	;cmp	bl, bh
  2329                              <1> 	;jne	short sleep0	
  2330                              <1> 	; 25/02/2014
  2331                              <1> 	;cmp word ptr [runq], 0
  2332                              <1> 	;ja short sleep0	
  2333                              <1> 	;retn
  2334                              <1> sleep0:
  2335                              <1> 	;
  2336 00004FB9 E849000000          <1> 	call	isintr
  2337                              <1> 	;jnz	sysret
  2338                              <1> 		; / wait for event
  2339                              <1>        		; jsr r0,isintr / check to see if interrupt 
  2340                              <1> 			      ; / or quit from user
  2341                              <1>                		; br 2f / something happened
  2342                              <1> 			      ; / yes, his interrupt so return
  2343                              <1>                      	      ;	/ to user
  2344                              <1> 	; 24/12/2021
  2345 00004FBE 7405                <1> 	jz	short sleep_2
  2346                              <1> sleep_3:
  2347 00004FC0 E92DEBFFFF          <1> 	jmp	sysret
  2348                              <1> sleep_2:
  2349                              <1> 	; 30/06/2015
  2350 00004FC5 0FB6DC              <1>     	movzx	ebx, ah ; 30/06/2015
  2351 00004FC8 81C3[386B0000]      <1> 	add	ebx, wlist
  2352 00004FCE 8A03                <1> 	mov	al, [ebx]
  2353 00004FD0 20C0                <1> 	and	al, al
  2354 00004FD2 7407                <1> 	jz	short sleep1
  2355 00004FD4 53                  <1> 	push	ebx
  2356 00004FD5 E82DFFFFFF          <1> 	call	putlu
  2357 00004FDA 5B                  <1> 	pop	ebx
  2358                              <1> sleep1:
  2359 00004FDB A0[E76E0000]        <1> 	mov	al, [u.uno]    
  2360 00004FE0 8803                <1>   	mov	[ebx], al 	; put the process number
  2361                              <1> 				; in the wait channel
  2362                              <1> 		; mov (r0)+,r1 / put number of wait channel in r1
  2363                              <1> 		; movb wlist(r1),-(sp) / put old process number in there,
  2364                              <1> 				     ; / on the stack
  2365                              <1>        		; movb u.uno,wlist(r1) / put process number of process
  2366                              <1> 				     ; / to put to sleep in there
  2367                              <1>         ; 15/09/2015
  2368 00004FE2 0FB6D8              <1> 	movzx	ebx, al
  2369 00004FE5 C683[176C0000]04    <1>         mov     byte [ebx+p.stat-1], 4 ; SSLEEP
  2370                              <1> 	; 26/02/2022 (p.waitc is not used)
  2371                              <1> 	;inc	ah
  2372                              <1> 	;mov	[ebx+p.waitc-1], ah ; wait channel + 1
  2373                              <1> 	;
  2374 00004FEC 66FF35[7F6E0000]    <1> 	push    word [cdev]
  2375                              <1> 		; mov cdev,-(sp) / nothing happened in isintr so
  2376 00004FF3 E842FEFFFF          <1> 	call	swap
  2377                              <1>        		; jsr r0,swap / swap out process that needs to sleep
  2378 00004FF8 668F05[7F6E0000]    <1>         pop     word [cdev]
  2379                              <1> 		; mov (sp)+,cdev / restore device
  2380 00004FFF E803000000          <1> 	call	isintr
  2381                              <1> 	; 22/09/2013
  2382                              <1> 	;jnz	sysret         
  2383                              <1> 		; jsr r0,isintr / check for interrupt of new process
  2384                              <1>                		; br 2f / yes, return to new user
  2385                              <1> 		; movb (sp)+,r1 / no, r1 = old process number that was 
  2386                              <1> 				; / originally on the wait channel
  2387                              <1>        		; beq 1f / if 0 branch
  2388                              <1>   		; mov $runq+4,r2 / r2 points to lowest priority queue
  2389                              <1>        		; mov $300,*$ps / processor priority = 6
  2390                              <1> 		; jsr r0,putlu / create link to old process number
  2391                              <1>        		; clr *$ps / clear the status; process priority = 0
  2392                              <1> 	; 24/12/2021
  2393 00005004 75BA                <1> 	jnz	short sleep_3 ; jump to sysret
  2394                              <1>      ;1:
  2395 00005006 C3                  <1> 	retn
  2396                              <1> 		; rts r0 / return
  2397                              <1>      ;2:
  2398                              <1>         ;;jmp	sysret
  2399                              <1> 		; jmp sysret / return to user
  2400                              <1> 
  2401                              <1> isintr:
  2402                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2403                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2404                              <1> 	;
  2405                              <1> 	; 09/05/2013 - 30/05/2014
  2406                              <1> 	;
  2407                              <1> 	; Retro UNIX 8086 v1 modification !
  2408                              <1> 	; (Process/task switching and quit routine by using
  2409                              <1> 	; Retro UNIX 8086 v1 keyboard interrupt output.))
  2410                              <1> 	;
  2411                              <1> 	; Retro UNIX 8086 v1 modification:
  2412                              <1> 	; 'isintr' checks if user interrupt request is enabled
  2413                              <1> 	;  and there is a 'quit' request by user;
  2414                              <1> 	;  otherwise, 'isintr' will return with zf=1 that means
  2415                              <1> 	;  "nothing to do". (20/10/2013)
  2416                              <1> 	;
  2417                              <1> 	; 20/10/2013
  2418 00005007 66833D[C86E0000]00  <1> 	cmp 	word [u.ttyp], 0 ; has process got a tty ?
  2419 0000500F 761F                <1> 	jna	short isintr2 ; retn
  2420                              <1> 	; 03/09/2013
  2421                              <1> 	; (nothing to do)
  2422                              <1> 	;retn
  2423                              <1> 	; 22/09/2013
  2424 00005011 66833D[DC6E0000]00  <1> 	cmp	word [u.intr], 0
  2425 00005019 7615                <1> 	jna	short isintr2 ; retn
  2426                              <1> 	; 30/05/2014
  2427                              <1> 	;push	ax
  2428                              <1> 	; 24/12/2021
  2429 0000501B 50                  <1> 	push	eax
  2430 0000501C 66A1[DE6E0000]      <1> 	mov	ax, [u.quit]
  2431 00005022 6609C0              <1> 	or	ax, ax ; 0 ?
  2432 00005025 7408                <1> 	jz	short isintr1 ; zf = 1
  2433 00005027 6683F8FE            <1> 	cmp	ax, 0FFFEh  ; 'ctrl + brk' check
  2434 0000502B 7702                <1> 	ja	short isintr1 ; 0FFFFh, zf = 0
  2435                              <1> 	;xor	ax, ax ; zf = 1
  2436                              <1> 	; 24/12/2021
  2437 0000502D 31C0                <1> 	xor	eax, eax ; zf = 1
  2438                              <1> isintr1:
  2439                              <1> 	;pop	ax
  2440                              <1> 	; 24/12/2021
  2441 0000502F 58                  <1> 	pop	eax
  2442                              <1> isintr2: ; 22/09/2013
  2443                              <1> 	; zf=1 -> nothing to do
  2444 00005030 C3                  <1> 	retn
  2445                              <1> 
  2446                              <1> 	; UNIX v1 original 'isintr' routine... 
  2447                              <1>        	;mov     r1,-(sp) / put number of wait channel on the stack
  2448                              <1>        	;mov     r2,-(sp) / save r2
  2449                              <1>        	;mov     u.ttyp,r1 / r1 = pointer to buffer of process control
  2450                              <1>         ;                 / typewriter
  2451                              <1>        	;beq     1f / if 0, do nothing except skip return
  2452                              <1>        	;movb    6(r1),r1 / put interrupt char in the tty buffer in r1
  2453                              <1>        	;beq     1f / if its 0 do nothing except skip return
  2454                              <1>        	;cmp     r1,$177 / is interrupt char = delete?
  2455                              <1>        	;bne     3f / no, so it must be a quit (fs)
  2456                              <1>        	;tst     u.intr / yes, value of u.intr determines handling
  2457                              <1>         ;              / of interrupts
  2458                              <1>        	;bne     2f / if not 0, 2f. If zero do nothing.
  2459                              <1>      ;1:
  2460                              <1>        	;tst     (r0)+ / bump r0 past system return (skip)
  2461                              <1>      ;4:
  2462                              <1>        	;mov     (sp)+,r2 / restore r1 and r2
  2463                              <1>        	;mov     (sp)+,r1
  2464                              <1>        	;rts     r0
  2465                              <1>      ;3: / interrupt char = quit (fs)
  2466                              <1>        	;tst     u.quit / value of u.quit determines handling of quits
  2467                              <1>        	;beq     1b / u.quit = 0 means do nothing
  2468                              <1>      ;2: / get here because either u.intr <> 0 or u.qult <> O
  2469                              <1>        	;mov     $tty+6,r1 / move pointer to tty block into r1
  2470                              <1>      ;1: / find process control tty entry in tty block
  2471                              <1>        	;cmp     (r1),u.ttyp / is this the process control tty buffer?
  2472                              <1>        	;beq     1f / block found go to 1f
  2473                              <1>        	;add     $8,r1 / look at next tty block
  2474                              <1>        	;cmp     r1,$tty+[ntty*8]+6 / are we at end of tty blocks
  2475                              <1>        	;blo     1b / no
  2476                              <1>        	;br      4b / no process control tty found so go to 4b
  2477                              <1>      ;1:
  2478                              <1>        	;mov     $240,*$ps / set processor priority to 5
  2479                              <1>        	;movb    -3(r1),0f / load getc call argument; character llst
  2480                              <1>         ;                  / identifier
  2481                              <1>        	;inc     0f / increment
  2482                              <1>      ;1:
  2483                              <1>        	;jsr     r0,getc; 0:.. / erase output char list for control
  2484                              <1>         ;        br 4b / process tty. This prevents a line of stuff
  2485                              <1>         ;             / being typed out after you hit the interrupt
  2486                              <1>         ;             / key
  2487                              <1>        	;br      1b
  2100                                  %include 'u5.s'        ; 03/06/2015
  2101                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS5.INC
  2102                              <1> ; Last Modification: 22/04/2022
  2103                              <1> ; ----------------------------------------------------------------------------
  2104                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2105                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2106                              <1> ;
  2107                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2108                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2109                              <1> ; <Bell Laboratories (17/3/1972)>
  2110                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2111                              <1> ;
  2112                              <1> ; Retro UNIX 8086 v1 - U5.ASM (07/08/2013) //// UNIX v1 -> u5.s
  2113                              <1> ;
  2114                              <1> ; ****************************************************************************
  2115                              <1> 
  2116                              <1> mget:
  2117                              <1> 	; 22/04/2022
  2118                              <1> 	; 09/01/2022
  2119                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2120                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2121                              <1> 	; 22/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2122                              <1> 	;
  2123                              <1> 	; Get existing or (allocate) a new disk block for file
  2124                              <1> 	; 
  2125                              <1> 	; INPUTS ->
  2126                              <1> 	;    u.fofp (file offset pointer)
  2127                              <1> 	;    inode 
  2128                              <1> 	;    u.off (file offset)
  2129                              <1> 	; OUTPUTS ->
  2130                              <1> 	;    r1 (physical block number)
  2131                              <1> 	;    r2, r3, r5 (internal)
  2132                              <1> 	;
  2133                              <1> 	; ((AX = R1)) output
  2134                              <1> 	;    (Retro UNIX Prototype : 05/03/2013 - 14/11/2012, UNIXCOPY.ASM)
  2135                              <1>         ;    ((Modified registers: eDX, eBX, eCX, eSI, eDI, eBP))  
  2136                              <1> 
  2137                              <1> 		; mov *u.fofp,mq / file offset in mq
  2138                              <1> 		; clr ac / later to be high sig
  2139                              <1> 		; mov $-8,lsh   / divide ac/mq by 256.
  2140                              <1> 		; mov mq,r2
  2141                              <1> 		; bit $10000,i.flgs / lg/sm is this a large or small file
  2142                              <1> 		; bne 4f / branch for large file
  2143                              <1> mget_0:	
  2144                              <1> 	; 09/01/2022
  2145 00005031 29C0                <1> 	sub	eax, eax
  2146 00005033 29D2                <1> 	sub	edx, edx
  2147 00005035 29C9                <1> 	sub	ecx, ecx
  2148 00005037 29DB                <1> 	sub	ebx, ebx
  2149                              <1> 
  2150 00005039 8B35[A86E0000]      <1>         mov     esi, [u.fofp]
  2151                              <1>         ;movzx	ebx, byte [esi+1]
  2152                              <1> 	; 09/01/2022
  2153 0000503F 46                  <1> 	inc	esi
  2154 00005040 8A1E                <1> 	mov	bl, [esi]
  2155                              <1> 
  2156                              <1> 	; BX = r2
  2157                              <1>         ; 24/12/2021
  2158 00005042 F605[996B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2159                              <1> 	;test 	word [i.flgs], 4096 ; 1000h
  2160                              <1> 				  ; is this a large or small file
  2161 00005049 756C                <1> 	jnz 	short mget_5 ; 4f ; large file
  2162                              <1> 
  2163 0000504B F6C3F0              <1>         test    bl, 0F0h ; !0Fh                    
  2164                              <1> 		; bit $!17,r2
  2165 0000504E 7525                <1> 	jnz 	short mget_2
  2166                              <1> 		; bne 3f / branch if r2 greater than or equal to 16
  2167 00005050 80E30E              <1>         and     bl, 0Eh  
  2168                              <1> 		; bic $!16,r2 / clear all bits but bits 1,2,3
  2169                              <1> 	; 09/01/2021
  2170 00005053 668B83[9E6B0000]    <1> 	mov	ax, [ebx+i.dskp]
  2171                              <1> 	;movzx 	eax, word [ebx+i.dskp] ; AX = R1, physical block number
  2172                              <1> 		; mov i.dskp(r2),r1 / r1 has physical block number
  2173                              <1> 	; 24/12/2021
  2174 0000505A 09C0                <1> 	or	eax, eax
  2175                              <1> 	;or 	ax, ax
  2176 0000505C 7516                <1> 	jnz 	short mget_1 
  2177                              <1> 		; bne 2f / if physical block num is zero then need a new block
  2178                              <1> 		       ; / for file
  2179 0000505E E8A6000000          <1> 	call 	alloc
  2180                              <1> 		; jsr r0,alloc / allocate a new block
  2181                              <1>          ; eAX (r1) = Physical block number
  2182 00005063 668983[9E6B0000]    <1> 	mov 	[ebx+i.dskp], ax
  2183                              <1> 		; mov r1,i.dskp(r2) / physical block number stored in i-node
  2184 0000506A E835020000          <1> 	call 	setimod	
  2185                              <1> 		; jsr r0,setimod / set inode modified byte (imod)
  2186 0000506F E8C2FEFFFF          <1> 	call	clear
  2187                              <1> 		; jsr r0,clear / zero out disk/drum block just allocated
  2188                              <1> mget_1: ; 2:
  2189                              <1>         ; eAX (r1) = Physical block number
  2190 00005074 C3                  <1> 	retn 
  2191                              <1> 		; rts r0
  2192                              <1> mget_2: ; 3: / adding on block which changes small file to a large file
  2193 00005075 E88F000000          <1> 	call 	alloc
  2194                              <1> 		; jsr r0,alloc / allocate a new block for this file;
  2195                              <1> 	                     ; / block number in r1
  2196                              <1>         ; eAX (r1) = Physical block number
  2197 0000507A E8690C0000          <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> 	; 09/01/2022
  2202 0000507F 31C9                <1> 	xor	ecx, ecx
  2203 00005081 B108                <1> 	mov	cl, 8
  2204                              <1> 	;mov 	ecx, 8  ; R3, transfer old physical block pointers
  2205                              <1> 		   ; into new indirect block area for the new
  2206                              <1> 		   ; large file		
  2207 00005083 89DF                <1> 	mov 	edi, ebx ; r5
  2208 00005085 BE[9E6B0000]        <1> 	mov 	esi, i.dskp 
  2209                              <1> 		; mov $8.,r3 / next 6 instructions transfer old physical 
  2210                              <1> 			   ; / block pointers
  2211                              <1> 		; mov $i.dskp,r2 / into new indirect block for the new 
  2212                              <1> 			  ; / large file
  2213                              <1> 	; 22/04/2022
  2214 0000508A 50                  <1> 	push	eax ; * ; bugfix
  2215                              <1> 
  2216                              <1> 	;xor 	ax, ax ; mov ax, 0
  2217                              <1> 	; 24/12/2021
  2218 0000508B 31C0                <1> 	xor	eax, eax
  2219                              <1> mget_3: ;1:
  2220 0000508D 66A5                <1> 	movsw
  2221                              <1> 		; mov (r2),(r5)+
  2222 0000508F 668946FE            <1> 	mov 	[esi-2], ax
  2223                              <1> 		; clr (r2)+
  2224 00005093 E2F8                <1> 	loop	mget_3 ; 1b
  2225                              <1> 		; dec r3
  2226                              <1> 		; bgt 1b
  2227                              <1> 
  2228 00005095 B1F8                <1> 	mov 	cl, 256-8
  2229                              <1> 		; mov $256.-8.,r3 / clear rest of data buffer
  2230                              <1> mget_4:	; 1
  2231 00005097 F366AB              <1> 	rep 	stosw
  2232                              <1> 		; clr (r5)+
  2233                              <1> 		; dec r3
  2234                              <1> 		; bgt 1b
  2235                              <1> 
  2236                              <1> 	; 22/04/2022
  2237                              <1> 	;pop	eax ; * ; bugfix
  2238                              <1> 
  2239                              <1> 	; 24/03/2013
  2240                              <1>         ; AX (r1) = Physical block number
  2241 0000509A E8650C0000          <1> 	call	dskwr
  2242                              <1> 		; jsr r0,dskwr / write new indirect block on disk
  2243                              <1> 
  2244                              <1> 	; 22/04/2022
  2245 0000509F 58                  <1> 	pop	eax ; * ; bugfix
  2246                              <1> 
  2247                              <1>         ; eAX (r1) = Physical block number
  2248 000050A0 66A3[9E6B0000]      <1> 	mov 	[i.dskp], ax
  2249                              <1> 		; mov r1,i.dskp / put pointer to indirect block in i-node
  2250                              <1> 	; 09/01/2022
  2251 000050A6 800D[996B0000]10    <1> 	or	byte [i.flgs+1], 10h
  2252                              <1> 	;or 	word [i.flgs], 4096 ; 1000h
  2253                              <1> 		; bis $10000,i.flgs / set large file bit 
  2254                              <1> 				  ; / in i.flgs word of i-node
  2255 000050AD E8F2010000          <1> 	call	setimod
  2256                              <1> 		; jsr r0,setimod / set i-node modified flag
  2257 000050B2 E97AFFFFFF          <1>         jmp     mget_0 
  2258                              <1> 		; br mget
  2259                              <1> 
  2260                              <1> mget_5:  ; 4 ; large file
  2261                              <1> 		; mov $-8,lsh / divide byte number by 256.
  2262                              <1> 		; bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
  2263                              <1> 			    ; / in indirect block
  2264                              <1> 		; mov r2,-(sp) / save on stack (*)
  2265                              <1> 		; mov mq,r2 / calculate offset in i-node for pointer to proper
  2266                              <1>        		          ; / indirect block
  2267                              <1> 		; bic $!16,r2
  2268 000050B7 80E3FE              <1>         and     bl, 0FEh ; bh = 0
  2269 000050BA 53                  <1>         push    ebx  ; i-node pointer offset in indirect block  (*) 
  2270                              <1>         ; 01/03/2013 Max. possible BX (offset) value is 127 (65535/512)
  2271                              <1> 	; 	     for this file system (offset 128 to 255 not in use)
  2272                              <1> 	; There is always 1 indirect block for this file system
  2273                              <1> 	; 09/01/2022
  2274 000050BB 66A1[9E6B0000]      <1> 	mov	ax, [i.dskp]
  2275                              <1> 	;movzx 	eax, word [i.dskp] ; i.dskp[0]
  2276                              <1> 		; mov i.dskp(r2),r1
  2277                              <1> 	; 09/01/2022
  2278 000050C1 09C0                <1> 	or	eax, eax
  2279                              <1> 	;or 	ax, ax ; R1
  2280 000050C3 7515                <1> 	jnz 	short mget_6 ; 2f
  2281                              <1> 		; bne 2f / if no indirect block exists
  2282 000050C5 E83F000000          <1> 	call 	alloc
  2283                              <1> 		; jsr r0,alloc / allocate a new block
  2284 000050CA 66A3[9E6B0000]      <1> 	mov 	[i.dskp], ax  ; 03/03/2013
  2285                              <1> 		; mov r1,i.dskp(r2) / put block number of new block in i-node
  2286 000050D0 E8CF010000          <1> 	call 	setimod
  2287                              <1> 		; jsr r0,setimod / set i-node modified byte
  2288                              <1> 	; eAX = new block number
  2289 000050D5 E85CFEFFFF          <1> 	call 	clear
  2290                              <1> 		; jsr r0,clear / clear new block
  2291                              <1> mget_6: ;2
  2292                              <1> 	; 05/03/2013
  2293                              <1> 	; eAX = r1, physical block number (of indirect block)
  2294 000050DA E8970B0000          <1> 	call 	dskrd ; read indirect block
  2295                              <1> 		; jsr r0,dskrd / read in indirect block
  2296 000050DF 5A                  <1> 	pop 	edx  ; R2, get offset (*)
  2297                              <1> 		; mov (sp)+,r2 / get offset
  2298                              <1> 	; eAX = r1, physical block number (of indirect block)
  2299 000050E0 50                  <1> 	push 	eax ; ** ; 24/03/2013
  2300                              <1> 		; mov r1,-(sp) / save block number of indirect block on stack
  2301                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2302 000050E1 01D3                <1> 	add 	ebx, edx ; / r5 points to first word in indirect block, r2
  2303                              <1> 		; add r5,r2 / r5 points to first word in indirect block, r2
  2304                              <1> 	                  ; / points to location of inter
  2305                              <1> 	; 09/01/2022
  2306 000050E3 668B03              <1> 	mov	ax, [ebx]
  2307                              <1> 	;movzx 	eax, word [ebx] ; put physical block no of block
  2308                              <1> 			      ; in file sought in R1 (AX)
  2309                              <1> 		; mov (r2),r1 / put physical block no of block in file
  2310                              <1> 	               	    ; / sought in r1
  2311                              <1> 	; 09/01/2022
  2312 000050E6 09C0                <1> 	or	eax, eax
  2313                              <1> 	;or 	ax, ax
  2314 000050E8 751D                <1>         jnz 	short mget_7 ; 2f
  2315                              <1> 		; bne 2f / if no block exists 
  2316 000050EA E81A000000          <1> 	call 	alloc
  2317                              <1> 		; jsr r0,alloc / allocate a new block
  2318 000050EF 668903              <1> 	mov 	[ebx], ax ; R1
  2319                              <1> 		; mov r1,(r2) / put new block number into proper location in
  2320                              <1> 	                    ; / indirect block
  2321 000050F2 5A                  <1> 	pop	edx ; ** ; 24/03/2013
  2322                              <1> 		; mov (sp)+,r1 / get block number of indirect block
  2323 000050F3 52                  <1> 	push 	edx ; ** ; 31/07/2013
  2324 000050F4 50                  <1> 	push	eax ; * ; 24/03/2013, 31/07/2013 (new block number)
  2325 000050F5 89D0                <1> 	mov	eax, edx ; 24/03/2013
  2326                              <1> 		; mov (r2),-(sp) / save block number of new block
  2327                              <1> 	; eAX (r1) = physical block number (of indirect block)
  2328 000050F7 E8EC0B0000          <1> 	call 	wslot
  2329                              <1> 		; jsr r0,wslot
  2330                              <1>         ; eAX (r1) = physical block number
  2331                              <1> 	; eBX (r5) = pointer to buffer (indirect block)
  2332 000050FC E8030C0000          <1> 	call 	dskwr
  2333                              <1> 	; eAX = r1 = physical block number (of indirect block)
  2334                              <1> 		; jsr r0,dskwr / write newly modified indirect block 
  2335                              <1> 			     ; / back out on disk
  2336 00005101 58                  <1> 	pop	eax ; *  ; 31/07/2013
  2337                              <1> 		; mov (sp),r1 / restore block number of new block	
  2338                              <1> 	; eAX (r1) = physical block number of new block
  2339 00005102 E82FFEFFFF          <1> 	call 	clear
  2340                              <1> 		; jsr r0,clear / clear new block	
  2341                              <1> mget_7: ; 2
  2342 00005107 5A                  <1> 	pop 	edx ; **
  2343                              <1> 		; tst (sp)+ / bump stack pointer
  2344                              <1> 	; eAX (r1) = Block number of new block
  2345 00005108 C3                  <1> 	retn
  2346                              <1> 		; rts r0
  2347                              <1> 
  2348                              <1> alloc:
  2349                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2350                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2351                              <1> 	; 01/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2352                              <1> 	;
  2353                              <1> 	; get a free block and 
  2354                              <1> 	; set the corresponding bit in the free storage map
  2355                              <1> 	; 
  2356                              <1> 	; INPUTS ->
  2357                              <1> 	;    cdev (current device)
  2358                              <1> 	;    r2 
  2359                              <1> 	;    r3
  2360                              <1> 	; OUTPUTS ->
  2361                              <1> 	;    r1 (physical block number of block assigned)
  2362                              <1> 	;    smod, mmod, systm (super block), mount (mountable super block)	
  2363                              <1> 	;
  2364                              <1> 	; ((AX = R1)) output
  2365                              <1> 	;    (Retro UNIX Prototype : 14/11/2012 - 21/07/2012, UNIXCOPY.ASM)
  2366                              <1>         ;    ((Modified registers: DX, CX))  
  2367                              <1> 
  2368                              <1> 		;mov r2,-(sp) / save r2, r3 on stack
  2369                              <1> 		;mov r3,-(sp)
  2370                              <1> 	;push 	ecx
  2371 00005109 53                  <1> 	push 	ebx ; R2
  2372                              <1> 	;push 	edx ; R3
  2373 0000510A BB[587B0000]        <1> 	mov 	ebx, systm ; SuperBlock 
  2374                              <1> 		; mov $systm,r2 / start of inode and free storage map for drum
  2375 0000510F 803D[7F6E0000]00    <1> 	cmp 	byte [cdev], 0
  2376                              <1> 		; tst cdev
  2377 00005116 7605                <1> 	jna	short alloc_1
  2378                              <1> 		; beq 1f / drum is device
  2379 00005118 BB[607D0000]        <1> 	mov	ebx, mount
  2380                              <1> 		; mov $mount,r2 / disk or tape is device, start of inode and
  2381                              <1> 			      ; / free storage map
  2382                              <1> alloc_1: ; 1
  2383                              <1> 	; 09/01/2022
  2384                              <1> 	;sub	ecx, ecx
  2385                              <1> 	;sub	edx, edx
  2386                              <1> 	;sub	eax, eax
  2387                              <1> 
  2388 0000511D 668B0B              <1>         mov	cx, [ebx]
  2389                              <1> 		; mov (r2)+,r1 / first word contains number of bytes in free
  2390                              <1> 			     ; / storage map
  2391                              <1> 	; 09/01/2022
  2392 00005120 C1E103              <1> 	shl	ecx, 3
  2393                              <1> 	;shl	cx, 3
  2394                              <1> 		; asl r1 / multiply r1 by eight gives 
  2395                              <1> 		; number of blocks in device
  2396                              <1> 		; asl r1
  2397                              <1> 		; asl r1
  2398                              <1> 	;;push	cx ;; 01/08/2013
  2399                              <1> 		; mov r1,-(sp) / save # of blocks in device on stack
  2400 00005123 31C0                <1> 	xor 	eax, eax ; 0
  2401                              <1> 		; clr r1 / r1 contains bit count of free storage map
  2402                              <1> alloc_2: ; 1
  2403 00005125 43                  <1> 	inc 	ebx ; 18/8/2012
  2404 00005126 43                  <1> 	inc 	ebx ; 
  2405 00005127 668B13              <1> 	mov 	dx, [ebx]
  2406                              <1> 		; mov (r2)+,r3 / word of free storage map in r3 
  2407                              <1> 	; 09/01/2022
  2408 0000512A 09D2                <1> 	or	edx, edx
  2409                              <1> 	;or 	dx, dx
  2410 0000512C 750D                <1> 	jnz 	short alloc_3 ; 1f
  2411                              <1> 		; bne 1f / branch if any free blocks in this word	
  2412 0000512E 6683C010            <1> 	add 	ax, 16
  2413                              <1> 		; add $16.,r1
  2414                              <1> 	; 09/01/2022
  2415 00005132 39C8                <1> 	cmp	eax, ecx
  2416                              <1> 	;cmp 	ax, cx    
  2417                              <1> 		; cmp r1 ,(sp) / have we examined all free storage bytes
  2418 00005134 72EF                <1> 	jb 	short alloc_2
  2419                              <1> 		; blo 1b
  2420                              <1> 	; 14/11/2015
  2421                              <1> 	; Note: If the super block buffer has wrong content (zero bytes)
  2422                              <1> 	;	because of a (DMA or another) r/w error, 
  2423                              <1> 	;	we will be here, at 'jmp panic' code address,
  2424                              <1> 	;	even if the (disk) file system space is not full !!!
  2425                              <1> 	;	(cx = 0)	
  2426                              <1> 	;
  2427 00005136 E94BE2FFFF          <1> 	jmp     panic 
  2428                              <1> 		; jmp panic / found no free storage
  2429                              <1> alloc_3: ; 1
  2430                              <1> 	; 09/01/2022
  2431 0000513B D1EA                <1> 	shr	edx, 1
  2432                              <1> 	;shr	dx, 1
  2433                              <1> 		; asr r3 / find a free block
  2434 0000513D 7203                <1> 	jc	short alloc_4 ; 1f
  2435                              <1> 		; bcs 1f / branch when free block found; bit for block k
  2436                              <1> 		       ; / is in byte k/8 / in bit k (mod 8)
  2437                              <1> 	; 09/01/2022
  2438 0000513F 40                  <1> 	inc	eax
  2439                              <1> 	;inc	ax
  2440                              <1> 		; inc r1 / increment bit count in bit k (mod8)
  2441 00005140 EBF9                <1> 	jmp 	short alloc_3
  2442                              <1> 		; br 1b
  2443                              <1> alloc_4: ; 1:
  2444                              <1> 	;; pop cx ;; 01/08/2013
  2445                              <1> 		; tst (sp)+ / bump sp
  2446                              <1> 	; 02/04/2013 
  2447 00005142 E829000000          <1> 	call	free3
  2448                              <1> 		; jsr r0,3f / have found a free block
  2449                              <1> 	; 21/8/2012
  2450 00005147 66F7D2              <1> 	not 	dx ; masking bit is '0' and others are '1'
  2451 0000514A 662113              <1> 	and	[ebx], dx   ;; 0 -> allocated 
  2452                              <1> 		; bic r3,(r2) / set bit for this block 
  2453                              <1> 		            ; / i.e. assign block
  2454                              <1> 		; br 2f
  2455 0000514D EB09                <1> 	jmp 	short alloc_5
  2456                              <1> 
  2457                              <1> free:
  2458                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2459                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2460                              <1> 	; 07/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2461                              <1> 	;
  2462                              <1> 	; calculates byte address and bit position for given block number
  2463                              <1> 	; then sets the corresponding bit in the free storage map
  2464                              <1> 	; 
  2465                              <1> 	; INPUTS ->
  2466                              <1> 	;    r1 - block number for a block structured device
  2467                              <1> 	;    cdev - current device 
  2468                              <1> 	; OUTPUTS ->
  2469                              <1> 	;    free storage map is updated
  2470                              <1> 	;    smod is incremented if cdev is root device (fixed disk)
  2471                              <1> 	;    mmod is incremented if cdev is a removable disk 	
  2472                              <1> 	;
  2473                              <1> 	;  (Retro UNIX Prototype : 01/12/2012, UNIXCOPY.ASM)
  2474                              <1>         ;  ((Modified registers: DX, CX))  
  2475                              <1> 
  2476                              <1> 		;mov r2,-(sp) / save r2, r3
  2477                              <1> 		;mov r3,-(sp)
  2478                              <1> 	;push 	ecx
  2479 0000514F 53                  <1> 	push 	ebx ; R2
  2480                              <1> 	;push 	edx ; R3 
  2481                              <1> 
  2482 00005150 E81B000000          <1>         call    free3
  2483                              <1> 	     	; jsr r0,3f  / set up bit mask and word no. 
  2484                              <1> 				 ; / in free storage map for block
  2485 00005155 660913              <1> 	or 	[ebx], dx  
  2486                              <1> 	  	; bis r3, (r2) / set free storage block bit;
  2487                              <1> 			    ;  / indicates free block	
  2488                              <1> 	; 0 -> allocated, 1 -> free
  2489                              <1> 
  2490                              <1> alloc_5:
  2491                              <1> 	; 07/04/2013
  2492                              <1> free_1: ; 2:
  2493                              <1> 	;pop 	edx
  2494                              <1> 		; mov (sp)+,r3 / restore r2, r3
  2495 00005158 5B                  <1> 	pop	ebx
  2496                              <1> 		; mov (sp)+,r2
  2497                              <1> 	; pop	ecx
  2498 00005159 803D[7F6E0000]00    <1> 	cmp 	byte [cdev], 0
  2499                              <1> 		; tst cdev / cdev = 0, block structured, drum; 
  2500                              <1> 			 ; / cdev = 1, mountable device
  2501 00005160 7707                <1> 	ja	short alloc_6 ; 1f
  2502                              <1> 		; bne 1f
  2503                              <1> 	;mov	byte [smod], 1
  2504 00005162 FE05[8D6E0000]      <1> 	inc 	byte [smod]
  2505                              <1> 		; incb smod / set super block modified for drum
  2506                              <1> 	; eAX (r1) = block number
  2507 00005168 C3                  <1> 	retn
  2508                              <1> 		; rts r0
  2509                              <1> free_2:
  2510                              <1> alloc_6: ; 1:
  2511                              <1> 	;mov 	byte [mmod], 1
  2512 00005169 FE05[8E6E0000]      <1> 	inc 	byte [mmod]
  2513                              <1> 		; incb	mmod 
  2514                              <1> 		  ; / set super block modified for mountable device
  2515                              <1> 	; eAX (r1) = block number
  2516 0000516F C3                  <1> 	retn	
  2517                              <1> 		; rts r0
  2518                              <1> free3:
  2519                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2520                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2521                              <1> 	; 02/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2522                              <1> 	;
  2523                              <1> 	; free3 is called from 'alloc' and 'free' procedures
  2524                              <1> 	; 
  2525                              <1> alloc_free_3: ; 3
  2526                              <1> 	;mov 	dx, 1
  2527                              <1> 	; 09/01/2022
  2528 00005170 31D2                <1> 	xor	edx, edx
  2529 00005172 42                  <1> 	inc	edx
  2530                              <1> 	; edx = 1
  2531 00005173 88C1                <1> 	mov 	cl, al
  2532                              <1> 		; mov r1,r2 / block number, k, = 1		
  2533 00005175 80E10F              <1> 	and 	cl, 0Fh  ; 0Fh <-- (k) mod 16
  2534                              <1> 		; bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
  2535 00005178 7402                <1> 	jz 	short free4
  2536                              <1> 		; bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
  2537                              <1> 			       ; / (k) mod 8
  2538                              <1> 	;shl 	dx, cl
  2539                              <1> 	; 09/01/2022
  2540 0000517A D3E2                <1> 	shl	edx, cl
  2541                              <1> free4:
  2542 0000517C 0FB7D8              <1> 	movzx 	ebx, ax
  2543                              <1> 		; mov r1,r2 / divide block number by 16
  2544                              <1> 	; 09/01/2022
  2545 0000517F C1EB04              <1> 	shr	ebx, 4
  2546                              <1> 	;shr 	bx, 4
  2547                              <1> 		; asr r2
  2548                              <1> 		; asr r2
  2549                              <1> 		; asr r2
  2550                              <1> 		; asr r2
  2551                              <1> 		; bcc 1f / branch if bit 3 in r1 was 0 i.e., 
  2552                              <1> 		       ; / bit for block is in lower half of word
  2553                              <1> 		; swab r3 / swap bytes in r3; bit in upper half of word in free
  2554                              <1> 		        ; / storage map
  2555                              <1> alloc_free_4: ; 1
  2556                              <1> 	; 09/01/2022
  2557 00005182 D1E3                <1> 	shl	ebx, 1
  2558                              <1> 	;shl 	bx, 1
  2559                              <1> 		; asl r2 / multiply block number by 2; r2 = k/8
  2560 00005184 81C3[5A7B0000]      <1> 	add 	ebx, systm+2 ; SuperBlock+2
  2561                              <1> 		; add $systm+2,r2 / address of word of free storage map for drum
  2562                              <1> 	    		        ; / with block bit in it 	
  2563 0000518A 803D[7F6E0000]00    <1> 	cmp	byte [cdev], 0
  2564                              <1> 		; tst cdev
  2565 00005191 7606                <1> 	jna	short alloc_free_5
  2566                              <1> 		; beq 1f / cdev = 0 indicates device is drum
  2567 00005193 81C308020000        <1> 	add	ebx, mount - systm
  2568                              <1> 		; add $mount-systm,r2 / address of word of free storage map for
  2569                              <1> 				    ; / mountable device with bit of block to be
  2570                              <1> 				    ; / freed
  2571                              <1> alloc_free_5: ; 1 
  2572 00005199 C3                  <1> 	retn
  2573                              <1> 		; rts r0 / return to 'free'
  2574                              <1> 	      ; 2
  2575                              <1> 	        ; .byte	1,2,4,10,20,40,100,200 / masks for bits 0,...,7
  2576                              <1> 	
  2577                              <1> iget:
  2578                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2579                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2580                              <1> 	; 07/04/2013 - 07/08/2013 (Retro UNIX 8086 v1)
  2581                              <1> 	;
  2582                              <1> 	; get a new i-node whose i-number in r1 and whose device is in cdev
  2583                              <1> 	;
  2584                              <1> 	; ('iget' returns current i-number in r1, if input value of r1 is 0)
  2585                              <1> 	; 
  2586                              <1> 	; INPUTS ->
  2587                              <1> 	;    ii - current i-number, rootdir
  2588                              <1> 	;    cdev - new i-node device
  2589                              <1> 	;    idev - current i-node device
  2590                              <1> 	;    imod - current i-node modified flag
  2591                              <1> 	;    mnti - cross device file i-number
  2592                              <1> 	;    r1 - i-numbe rof new i-node
  2593                              <1> 	;    mntd - mountable device number		
  2594                              <1> 	; 	 
  2595                              <1> 	; OUTPUTS ->
  2596                              <1> 	;    cdev, idev, imod, ii, r1
  2597                              <1> 	;
  2598                              <1> 	; ((AX = R1)) input/output
  2599                              <1> 	;
  2600                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2601                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2602                              <1> 
  2603 0000519A 8A15[7F6E0000]      <1> 	mov	dl, [cdev] ; 18/07/2013
  2604 000051A0 8A35[7E6E0000]      <1> 	mov	dh, [idev] ; 07/08/2013
  2605                              <1> 	;
  2606 000051A6 663B05[7C6E0000]    <1> 	cmp 	ax, [ii]
  2607                              <1> 		; cmp r1,ii / r1 = i-number of current file
  2608 000051AD 7504                <1> 	jne 	short iget_1
  2609                              <1> 		; bne 1f
  2610 000051AF 38F2                <1> 	cmp	dl, dh
  2611                              <1> 		; cmp idev,cdev
  2612                              <1> 			  ; / is device number of i-node = current device
  2613 000051B1 7472                <1>         je      short iget_5
  2614                              <1> 		; beq 2f
  2615                              <1> iget_1: ; 1:
  2616 000051B3 30DB                <1> 	xor	bl, bl
  2617 000051B5 381D[8C6E0000]      <1> 	cmp	[imod], bl ; 0	
  2618                              <1> 		; tstb imod / has i-node of current file
  2619                              <1> 			  ; / been modified i.e., imod set
  2620 000051BB 7629                <1> 	jna	short iget_2
  2621                              <1> 		; beq 1f
  2622 000051BD 881D[8C6E0000]      <1> 	mov	[imod], bl ; 0
  2623                              <1> 		;  clrb	imod / if it has, 
  2624                              <1> 			   ; / we must write the new i-node out on disk
  2625                              <1> 	; 24/12/2021
  2626 000051C3 50                  <1> 	push	eax ; *
  2627                              <1> 	;push	ax
  2628                              <1> 		; mov r1,-(sp)
  2629                              <1> 	;mov	dl, [cdev]
  2630 000051C4 52                  <1> 	push	edx ; **
  2631                              <1> 	;push	dx
  2632                              <1> 		; mov cdev,-(sp)
  2633 000051C5 66A1[7C6E0000]      <1> 	mov	ax, [ii]
  2634                              <1> 		; mov ii,r1
  2635                              <1> 	;mov	dh, [idev]
  2636 000051CB 8835[7F6E0000]      <1> 	mov	[cdev], dh
  2637                              <1> 		; mov idev,cdev
  2638 000051D1 FEC3                <1> 	inc	bl ; 1
  2639                              <1> 	; 31/07/2013
  2640 000051D3 881D[1C6F0000]      <1> 	mov     [rw], bl ; 1 == write 
  2641                              <1> 	;;28/07/2013 rw -> u.rw
  2642                              <1>         ;;mov   [u.rw], bl ; 1 == write
  2643 000051D9 E848000000          <1> 	call	icalc
  2644                              <1> 		; jsr r0,icalc; 1
  2645                              <1> 	;pop	dx
  2646                              <1> 	; 24/12/2021
  2647 000051DE 5A                  <1> 	pop	edx ; **
  2648 000051DF 8815[7F6E0000]      <1> 	mov	[cdev], dl
  2649                              <1> 		; mov (sp)+,cdev
  2650                              <1> 	; 24/12/2021
  2651 000051E5 58                  <1> 	pop	eax ; *
  2652                              <1> 	;pop	ax
  2653                              <1> 		; mov (sp)+,r1
  2654                              <1> iget_2: ; 1:
  2655 000051E6 6621C0              <1> 	and	ax, ax
  2656                              <1> 		; tst r1 / is new i-number non zero
  2657 000051E9 7434                <1> 	jz	short iget_4 ; 2f
  2658                              <1> 		; beq 2f / branch if r1=0
  2659                              <1> 
  2660                              <1> 	;mov 	dl, [cdev]
  2661 000051EB 08D2                <1> 	or	dl, dl
  2662                              <1> 		; tst cdev / is the current device number non zero
  2663                              <1> 			 ; / (i.e., device =/ drum)
  2664 000051ED 7517                <1> 	jnz	short iget_3 ;  1f
  2665                              <1> 		; bne 1f / branch 1f cdev =/ 0  ;; (cdev != 0)
  2666 000051EF 663B05[846E0000]    <1> 	cmp	ax, [mnti]			
  2667                              <1> 		; cmp r1,mnti / mnti is the i-number of the cross device
  2668                              <1> 			    ; / file (root directory of mounted device)
  2669 000051F6 750E                <1> 	jne	short iget_3 ; 1f
  2670                              <1> 		; bne 1f
  2671                              <1>         ;mov    bl, [mntd]
  2672 000051F8 FEC2                <1> 	inc	dl ; mov dl, 1 ; 17/07/2013
  2673 000051FA 8815[7F6E0000]      <1>         mov	[cdev], dl ; 17/07/2013 - 09/07/2013
  2674                              <1> 		; mov mntd,cdev / make mounted device the current device
  2675 00005200 66A1[886E0000]      <1> 	mov	ax, [rootdir]
  2676                              <1> 		; mov rootdir,r1
  2677                              <1> iget_3: ; 1:
  2678 00005206 66A3[7C6E0000]      <1> 	mov	[ii], ax
  2679                              <1> 		; mov r1,ii
  2680 0000520C 8815[7E6E0000]      <1> 	mov	[idev], dl ; cdev
  2681                              <1> 		; mov cdev,idev
  2682 00005212 30DB                <1> 	xor	bl, bl
  2683                              <1>         ; 31/07/2013
  2684 00005214 881D[1C6F0000]      <1> 	mov     [rw], bl ; 0 == read 
  2685                              <1> 	;;28/07/2013 rw -> u.rw       
  2686                              <1>         ;;mov   [u.rw], bl ; 0 = read
  2687 0000521A E807000000          <1> 	call	icalc
  2688                              <1> 		; jsr r0,icalc; 0 / read in i-node ii
  2689                              <1> iget_4: ; 2:
  2690 0000521F 66A1[7C6E0000]      <1> 	mov	ax, [ii]
  2691                              <1> 		; mov ii,r1
  2692                              <1> iget_5:
  2693 00005225 C3                  <1> 	retn
  2694                              <1> 		; rts r0
  2695                              <1> 
  2696                              <1> icalc:
  2697                              <1> 	; 04/04/2022 (47->31)
  2698                              <1> 	;	(Inode Table/List Address modification)
  2699                              <1> 	; 09/01/2022
  2700                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2701                              <1> 	; 02/07/2015
  2702                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2703                              <1> 	; 07/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2704                              <1> 	;
  2705                              <1> 	; calculate physical block number from i-number then
  2706                              <1> 	; read or write that block
  2707                              <1> 	;
  2708                              <1> 	; 'icalc' is called from 'iget'
  2709                              <1> 	;
  2710                              <1> 	; for original unix v1:
  2711                              <1> 	; / i-node i is located in block (i+31.)/16. and begins 32.*
  2712                              <1>        	; / (i+31.) mod 16. bytes from its start
  2713                              <1> 	;
  2714                              <1> 	; for retro unix 8086 v1:
  2715                              <1> 	;  i-node is located in block (i+47)/16 and
  2716                              <1> 	;  begins 32*(i+47) mod 16 bytes from its start
  2717                              <1> 	;
  2718                              <1> 	; INPUTS ->
  2719                              <1> 	;    r1 - i-number of i-node
  2720                              <1> 	; 	 
  2721                              <1> 	; OUTPUTS ->
  2722                              <1> 	;    inode r/w
  2723                              <1> 	;
  2724                              <1> 	; ((AX = R1)) input
  2725                              <1> 	;
  2726                              <1> 	;  (Retro UNIX Prototype : 14/07/2012 - 18/11/2012, UNIXCOPY.ASM)
  2727                              <1>         ;  ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))  
  2728                              <1> 	;
  2729 00005226 0FB7D0              <1> 	movzx	edx, ax	
  2730                              <1> 	;add	dx, 47
  2731                              <1> 	; 04/04/2022
  2732 00005229 6683C21F            <1> 	add	dx, 31
  2733 0000522D 89D0                <1> 	mov	eax, edx
  2734                              <1> 	;;add	ax, 47	; add 47 to inode number
  2735                              <1> 	;add	ax, 31
  2736                              <1> 		; add $31.,r1 / add 31. to i-number
  2737 0000522F 50                  <1> 	push	eax
  2738                              <1> 		; mov r1,-(sp) / save i+31. on stack
  2739                              <1> 	; 09/01/2022
  2740 00005230 C1E804              <1> 	shr	eax, 4
  2741                              <1> 	;shr 	ax, 4
  2742                              <1> 		; asr r1 / divide by 16.
  2743                              <1> 		; asr r1
  2744                              <1> 		; asr r1
  2745                              <1> 		; asr r1 / r1 contains block number of block
  2746                              <1> 		       ; / in which i-node exists
  2747 00005233 E83E0A0000          <1> 	call	dskrd
  2748                              <1> 		; jsr r0,dskrd / read in block containing i-node i.
  2749                              <1> 	; 31/07/2013
  2750 00005238 803D[1C6F0000]00    <1>         cmp     byte [rw], 0 ; Retro Unix 8086 v1 feature !
  2751                              <1> 	;; 28/07/2013 rw -> u.rw
  2752                              <1>         ;;cmp	byte [u.rw], 0 ; Retro Unix 8086 v1 feature !
  2753                              <1> 		; tst (r0)
  2754 0000523F 7605                <1> 	jna	short icalc_1
  2755                              <1> 		; beq 1f / branch to wslot when argument
  2756                              <1> 		       ; / in icalc call = 1
  2757                              <1> 	; eAX = r1 = block number
  2758 00005241 E8A20A0000          <1> 	call	wslot
  2759                              <1> 		; jsr r0,wslot / set up data buffer for write
  2760                              <1> 			     ; / (will be same buffer as dskrd got)
  2761                              <1> 	; eBX = r5 points to first word in data area for this block
  2762                              <1> icalc_1: ; 1:
  2763 00005246 5A                  <1> 	pop	edx 
  2764 00005247 83E20F              <1> 	and 	edx, 0Fh ; (i+31) mod 16 (2022) ; (i+47) mod 16
  2765                              <1> 		; bic $!17,(sp) / zero all but last 4 bits; 
  2766                              <1> 			      ; / gives (i+31.) mod 16
  2767 0000524A C1E205              <1> 	shl 	edx, 5
  2768                              <1> 	; eDX = 32 * ((i+31) mod 16) ; 32 * ((i+47) mod 16)
  2769 0000524D 89DE                <1> 	mov	esi, ebx  ; ebx points 1st word of the buffer
  2770 0000524F 01D6                <1> 	add	esi, edx  ; edx is inode offset in the buffer
  2771                              <1>           	; eSI (r5) points to first word in i-node i.	
  2772                              <1> 		; mov (sp)+,mq / calculate offset in data buffer; 
  2773                              <1> 			     ; / 32.*(i+31.)mod16
  2774                              <1> 		; mov $5,lsh / for i-node i.
  2775                              <1> 		; add mq,r5 / r5 points to first word in i-node i.
  2776 00005251 BF[986B0000]        <1> 	mov	edi, inode
  2777                              <1> 		; mov $inode,r1 / inode is address of first word 
  2778                              <1> 			      ; / of current i-node
  2779                              <1> 	; 09/01/2022
  2780 00005256 29C9                <1> 	sub	ecx, ecx
  2781 00005258 B108                <1> 	mov	cl, 8 
  2782                              <1> 	;mov 	ecx, 8 ; 02/07/2015(32 bit modification)
  2783                              <1> 		; mov $16.,r3
  2784                              <1>        ; 31/07/2013
  2785 0000525A 382D[1C6F0000]      <1>   	cmp     [rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2786                              <1>        ;;28/07/2013 rw -> u.rw                 
  2787                              <1>        ;;cmp    [u.rw], ch ; 0  ;; Retro Unix 8086 v1 feature !
  2788                              <1> 		; tst (r0)+ / branch to 2f when argument in icalc call = 0
  2789 00005260 7609                <1> 	jna	short icalc_3
  2790                              <1> 		; beq 2f / r0 now contains proper return address 
  2791                              <1> 		       ; / for rts r0
  2792                              <1> icalc_2: ; 1:
  2793 00005262 87F7                <1> 	xchg 	esi, edi
  2794                              <1> 	; overwrite old i-node (in buffer to be written)
  2795 00005264 F3A5                <1> 	rep 	movsd
  2796                              <1> 		; mov (r1)+,(r5)+ / over write old i-node
  2797                              <1> 		; dec r3
  2798                              <1> 		; bgt 1b
  2799                              <1> 	;call	dskwr
  2800                              <1> 		; jsr r0,dskwr / write inode out on device
  2801                              <1> 	;retn
  2802                              <1> 		; rts r0
  2803                              <1> 	; 24/12/2021
  2804 00005266 E9990A0000          <1> 	jmp	dskwr
  2805                              <1> 
  2806                              <1> icalc_3: ; 2:
  2807                              <1> 	; copy new i-node into inode area of (core) memory
  2808 0000526B F3A5                <1> 	rep 	movsd
  2809                              <1> 		; mov (r5)+,(r1)+ / read new i-node into 
  2810                              <1> 		                ; / "inode" area of core
  2811                              <1> 		; dec r3
  2812                              <1> 		; bgt 2b
  2813 0000526D C3                  <1> 	retn
  2814                              <1> 		; rts r0
  2815                              <1> 
  2816                              <1> access:
  2817                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2818                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2819                              <1> 	; 24/04/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  2820                              <1> 	;
  2821                              <1> 	; check whether user is owner of file or user has read or write
  2822                              <1> 	; permission (based on i.flgs).
  2823                              <1> 	;
  2824                              <1> 	; INPUTS ->
  2825                              <1> 	;    r1 - i-number of file
  2826                              <1> 	;    u.uid
  2827                              <1> 	; arg0 -> (owner flag mask)	 		
  2828                              <1> 	;     Retro UNIX 8086 v1 feature -> owner flag mask in DL (DX) 	 
  2829                              <1> 	; OUTPUTS ->
  2830                              <1> 	;    inode (or jump to error)
  2831                              <1> 	;
  2832                              <1> 	; ((AX = R1)) input/output
  2833                              <1> 	;
  2834                              <1>         ;  ((Modified registers: eCX, eBX, eDX, eSI, eDI, eBP))  
  2835                              <1> 	
  2836                              <1> 	;push	dx  ; save flags (DL)
  2837                              <1> 	; 24/12/2021
  2838 0000526E 52                  <1> 	push	edx ; save flags (DL)
  2839 0000526F E826FFFFFF          <1> 	call	iget
  2840                              <1> 		; jsr r0,iget / read in i-node for current directory
  2841                              <1> 			    ; / (i-number passed in r1)
  2842 00005274 8A0D[986B0000]      <1> 	mov	cl, [i.flgs]
  2843                              <1> 		; mov i.flgs,r2
  2844                              <1> 	; 24/12/2021
  2845 0000527A 5A                  <1> 	pop	edx ; restore flags (DL)
  2846                              <1> 	;pop	dx  ; restore flags (DL)
  2847 0000527B 8A35[E46E0000]      <1> 	mov	dh, [u.uid]
  2848 00005281 3A35[9B6B0000]      <1> 	cmp	dh, [i.uid]
  2849                              <1> 		; cmpb i.uid,u.uid / is user same as owner of file
  2850 00005287 7503                <1> 	jne	short access_1
  2851                              <1> 		; bne 1f / no, then branch
  2852 00005289 C0E902              <1> 	shr	cl, 2
  2853                              <1> 		; asrb r2 / shift owner read write bits into non owner
  2854                              <1> 		        ; / read/write bits
  2855                              <1> 		; asrb r2
  2856                              <1> access_1: ; 1:
  2857 0000528C 20D1                <1> 	and	cl, dl
  2858                              <1> 		; bit r2,(r0)+ / test read-write flags against argument
  2859                              <1> 			     ; / in access call
  2860 0000528E 7513                <1> 	jnz	short access_2
  2861                              <1> 		; bne 1f
  2862 00005290 08F6                <1> 	or	dh, dh	; super user (root) ?
  2863                              <1> 		; tstb u.uid
  2864 00005292 740F                <1> 	jz	short access_2 ; yes, super user
  2865                              <1> 	;jnz	error
  2866                              <1> 		; beq 1f
  2867                              <1> 		; jmp error
  2868 00005294 C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS 
  2868 0000529C 0000                <1>
  2869                              <1> 			; 'permission denied !' error
  2870 0000529E E92FE8FFFF          <1> 	jmp	error
  2871                              <1> 
  2872                              <1> access_2: ; 1:
  2873                              <1> 	; DL = flags
  2874 000052A3 C3                  <1> 	retn
  2875                              <1> 		; rts r0
  2876                              <1> 
  2877                              <1> setimod:
  2878                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2879                              <1> 	; 09/04/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2880                              <1> 	;
  2881                              <1> 	; 'setimod' sets byte at location 'imod' to 1; thus indicating that 
  2882                              <1> 	; the inode has been modified. Also puts the time of modification
  2883                              <1> 	; into the inode.
  2884                              <1> 	;
  2885                              <1> 	; (Retro UNIX Prototype : 14/07/2012 - 23/02/2013, UNIXCOPY.ASM)
  2886                              <1>         ; ((Modified registers: eDX, eCX, eBX)) 
  2887                              <1> 	;
  2888                              <1> 	
  2889                              <1> 	;push 	edx
  2890 000052A4 50                  <1> 	push	eax
  2891                              <1> 
  2892 000052A5 C605[8C6E0000]01    <1> 	mov 	byte [imod], 1
  2893                              <1> 		; movb $1,imod / set current i-node modified bytes
  2894                              <1> 	; Erdogan Tan 14-7-2012
  2895 000052AC E864E3FFFF          <1> 	call 	epoch
  2896                              <1> 		 ; mov s.time,i.mtim 
  2897                              <1> 			    ; / put present time into file modified time
  2898                              <1> 		 ; mov s.time+2,i.mtim+2
  2899                              <1> 
  2900 000052B1 A3[B26B0000]        <1> 	mov 	[i.mtim], eax
  2901                              <1> 	
  2902                              <1> 	; Retro UNIX 386 v1 modification ! (cmp)
  2903                              <1> 	; Retro UNIX 8086 v1 modification ! (test)
  2904 000052B6 833D[AE6B0000]00    <1> 	cmp	dword [i.ctim], 0
  2905 000052BD 7505                <1> 	jnz	short setimod_ok
  2906                              <1> 
  2907 000052BF A3[AE6B0000]        <1> 	mov 	[i.ctim], eax
  2908                              <1> 
  2909                              <1> setimod_ok: ; 31/07/2013
  2910 000052C4 58                  <1> 	pop	eax
  2911                              <1> 	;pop	edx
  2912                              <1> 	
  2913 000052C5 C3                  <1> 	retn
  2914                              <1> 		; rts r0
  2915                              <1> 
  2916                              <1> itrunc:
  2917                              <1> 	; 03/02/2022
  2918                              <1> 	; 09/01/2022
  2919                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1) 
  2920                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  2921                              <1> 	; 23/04/2013 - 01/08/2013 (Retro UNIX 8086 v1)
  2922                              <1> 	;
  2923                              <1> 	; 'itrunc' truncates a file whose i-number is given in r1
  2924                              <1> 	;  to zero length.
  2925                              <1> 	;
  2926                              <1> 	; INPUTS ->
  2927                              <1> 	;    r1 - i-number of i-node
  2928                              <1> 	;    i.dskp - pointer to contents or indirect block in an i-node
  2929                              <1> 	;    i.flgs - large file flag		
  2930                              <1> 	;    i.size - size of file	
  2931                              <1> 	; 	 
  2932                              <1> 	; OUTPUTS ->
  2933                              <1> 	;    i.flgs - large file flag is cleared
  2934                              <1> 	;    i.size - set to 0	
  2935                              <1> 	;    i.dskp .. i.dskp+16 - entire list is cleared
  2936                              <1> 	;    setimod - set to indicate i-node has been modified
  2937                              <1> 	;    r1 - i-number of i-node  					
  2938                              <1> 	;
  2939                              <1> 	; ((AX = R1)) input/output
  2940                              <1> 	;
  2941                              <1> 	;  (Retro UNIX Prototype : 01/12/2012 - 10/03/2013, UNIXCOPY.ASM)
  2942                              <1>         ;  ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2943                              <1> 
  2944 000052C6 E8CFFEFFFF          <1> 	call	iget
  2945                              <1> 		; jsr r0,iget
  2946 000052CB BE[9E6B0000]        <1> 	mov	esi, i.dskp
  2947                              <1> 		; mov $i.dskp,r2 / address of block pointers in r2
  2948 000052D0 31C0                <1> 	xor	eax, eax
  2949                              <1> itrunc_1: ; 1:
  2950 000052D2 66AD                <1> 	lodsw
  2951                              <1> 		; mov (r2)+,r1 / move physical block number into r1
  2952                              <1> 	; 09/01/2022
  2953 000052D4 09C0                <1> 	or	eax, eax
  2954                              <1> 	;or 	ax, ax
  2955 000052D6 7433                <1> 	jz	short itrunc_5
  2956                              <1> 		; beq 5f
  2957 000052D8 56                  <1> 	push	esi
  2958                              <1> 		; mov r2,-(sp)
  2959                              <1> 	; 09/01/2022
  2960 000052D9 F605[996B0000]10    <1> 	test	byte [i.flgs+1], 10h
  2961                              <1> 	;test	word [i.flgs], 1000h
  2962                              <1> 		; bit $10000,i.flgs / test large file bit?
  2963 000052E0 7423                <1> 	jz	short itrunc_4
  2964                              <1> 		; beq 4f / if clear, branch
  2965 000052E2 50                  <1> 	push	eax
  2966                              <1> 		; mov r1,-(sp) / save block number of indirect block
  2967 000052E3 E88E090000          <1> 	call	dskrd
  2968                              <1> 		; jsr r0,dskrd / read in block, 1st data word 
  2969                              <1> 			     ; / pointed to by r5
  2970                              <1> 	; eBX = r5 = Buffer data address (the 1st word)
  2971                              <1> 	; 09/01/2022
  2972 000052E8 31C9                <1> 	xor	ecx, ecx
  2973 000052EA FEC5                <1> 	inc	ch ; mov ch, 1
  2974                              <1> 	; ecx = 256
  2975                              <1> 	;mov	ecx, 256
  2976                              <1> 		; mov $256.,r3 / move word count into r3
  2977 000052EC 89DE                <1> 	mov	esi, ebx
  2978                              <1> itrunc_2: ; 2:
  2979 000052EE 66AD                <1> 	lodsw
  2980                              <1> 		; mov (r5)+,r1 / put 1st data word in r1; 
  2981                              <1> 			     ; / physical block number
  2982                              <1> 	; 09/01/2022
  2983 000052F0 21C0                <1> 	and	eax, eax
  2984                              <1> 	;and	ax, ax
  2985 000052F2 7407                <1> 	jz	short itrunc_3
  2986                              <1> 		; beq 3f / branch if zero
  2987                              <1> 	; 24/12/2021
  2988 000052F4 51                  <1> 	push	ecx
  2989                              <1> 	;push	cx
  2990                              <1> 		; mov r3,-(sp) / save r3, r5 on stack
  2991                              <1> 	;push	esi
  2992                              <1> 		; mov r5,-(sp)
  2993 000052F5 E855FEFFFF          <1> 	call	free
  2994                              <1> 		; jsr r0,free / free block in free storage map
  2995                              <1> 	;pop	esi
  2996                              <1> 		; mov(sp)+,r5
  2997                              <1> 	;pop	cx
  2998 000052FA 59                  <1> 	pop	ecx
  2999                              <1> 		; mov (sp)+,r3
  3000                              <1> itrunc_3: ; 3:
  3001 000052FB E2F1                <1> 	loop	itrunc_2
  3002                              <1> 		; dec r3 / decrement word count
  3003                              <1> 		; bgt 2b / branch if positive
  3004 000052FD 58                  <1> 	pop	eax
  3005                              <1> 		; mov (sp)+,r1 / put physical block number of 
  3006                              <1> 			     ; / indirect block
  3007                              <1> 	; 01/08/2013
  3008                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3009                              <1> 	; 03/02/2022
  3010 000052FE 8025[996B0000]EF    <1> 	and	byte [i.flgs+1], 0EFh
  3011                              <1> itrunc_4: ; 4:
  3012 00005305 E845FEFFFF          <1> 	call	free
  3013                              <1> 		; jsr r0,free / free indirect block
  3014 0000530A 5E                  <1> 	pop	esi
  3015                              <1> 		; mov (sp)+,r2
  3016                              <1> itrunc_5: ; 5:
  3017 0000530B 81FE[AE6B0000]      <1> 	cmp	esi, i.dskp+16
  3018                              <1> 		; cmp r2,$i.dskp+16.
  3019 00005311 72BF                <1> 	jb	short itrunc_1	
  3020                              <1> 		; bne 1b / branch until all i.dskp entries check
  3021                              <1> 	; 03/02/2022
  3022                              <1> 	;and	byte [i.flgs+1], 0EFh
  3023                              <1> 	; 01/08/2013
  3024                              <1> 	;and	word [i.flgs], 0EFFFh ; 1110111111111111b
  3025                              <1> 		; bic $10000,i.flgs / clear large file bit
  3026 00005313 BF[9E6B0000]        <1> 	mov	edi, i.dskp
  3027                              <1> 	;mov	cx, 8
  3028                              <1> 	;xor 	ax, ax
  3029                              <1> 	; 09/01/2022
  3030 00005318 29C9                <1> 	sub	ecx, ecx
  3031 0000531A B108                <1> 	mov	cl, 8
  3032 0000531C 29C0                <1> 	sub	eax, eax
  3033 0000531E 66A3[9C6B0000]      <1> 	mov	[i.size], ax ; 0
  3034                              <1> 		; clr i.size / zero file size
  3035 00005324 F366AB              <1> 	rep	stosw
  3036                              <1> 		; jsr r0,copyz; i.dskp; i.dskp+16. 
  3037                              <1> 			   ; / zero block pointers
  3038 00005327 E878FFFFFF          <1> 	call	setimod
  3039                              <1> 		; jsr r0,setimod / set i-node modified flag
  3040 0000532C 66A1[7C6E0000]      <1> 	mov	ax, [ii]
  3041                              <1> 		; mov ii,r1
  3042 00005332 C3                  <1> 	retn
  3043                              <1> 		; rts r0
  3044                              <1> 
  3045                              <1> imap:
  3046                              <1> 	; 11/02/2022
  3047                              <1> 	; 03/02/2022
  3048                              <1> 	; 03/06/2015 (Retro UNIX 386 v1 - Beginning)
  3049                              <1> 	; 26/04/2013 (Retro UNIX 8086 v1)
  3050                              <1> 	;
  3051                              <1> 	; 'imap' finds the byte in core (superblock) containing
  3052                              <1> 	; allocation bit for an i-node whose number in r1.
  3053                              <1> 	;
  3054                              <1> 	; INPUTS ->
  3055                              <1> 	;    r1 - contains an i-number
  3056                              <1> 	;    fsp - start of table containing open files
  3057                              <1> 	;
  3058                              <1> 	; OUTPUTS ->
  3059                              <1> 	;    r2 - byte address of byte with the allocation bit
  3060                              <1> 	;    mq - a mask to locate the bit position.	
  3061                              <1> 	;	  (a 1 is in calculated bit posisiton)
  3062                              <1> 	;
  3063                              <1> 	; ((AX = R1)) input/output
  3064                              <1> 	; ((DL/DX = MQ)) output
  3065                              <1> 	; ((BX = R2)) output
  3066                              <1> 	;
  3067                              <1> 	;    (Retro UNIX Prototype : 02/12/2012, UNIXCOPY.ASM)
  3068                              <1>         ;    ((Modified registers: eDX, eCX, eBX, eSI))  
  3069                              <1> 	;
  3070                              <1> 		; / get the byte that has the allocation bit for 
  3071                              <1> 		; / the i-number contained in r1
  3072                              <1> 	;mov	dx, 1
  3073 00005333 B201                <1> 	mov	dl, 1
  3074                              <1> 		; mov $1,mq / put 1 in the mq
  3075 00005335 0FB7D8              <1> 	movzx	ebx, ax
  3076                              <1> 		; mov r1,r2 / r2 now has i-number whose byte
  3077                              <1>  		          ; / in the map we must find
  3078 00005338 6683EB29            <1> 	sub	bx, 41
  3079                              <1> 		; sub $41.,r2 / r2 has i-41
  3080 0000533C 88D9                <1> 	mov	cl, bl
  3081                              <1> 		; mov r2,r3 / r3 has i-41
  3082 0000533E 80E107              <1> 	and	cl, 7
  3083                              <1> 		; bic $!7,r3 / r3 has (i-41) mod 8 to get 
  3084                              <1> 			   ; / the bit position
  3085 00005341 7402                <1> 	jz	short imap1
  3086                              <1> 	;shl	dx, cl
  3087 00005343 D2E2                <1> 	shl	dl, cl
  3088                              <1> 		; mov r3,lsh / move the 1 over (i-41) mod 8 positions
  3089                              <1> imap1:			   ; / to the left to mask the correct bit
  3090                              <1> 	; 03/02/2022
  3091 00005345 C1EB03              <1> 	shr	ebx, 3
  3092                              <1> 	;shr	bx, 3
  3093                              <1> 		; asr r2
  3094                              <1> 		; asr r2
  3095                              <1> 		; asr r2 / r2 has (i-41) base 8 of the byte number
  3096                              <1> 		       ; / from the start of the map
  3097                              <1> 		; mov r2,-(sp) / put (i-41) base 8 on the stack
  3098 00005348 BE[587B0000]        <1> 	mov	esi, systm
  3099                              <1> 		; mov $systm,r2 / r2 points to the in-core image of
  3100                              <1> 				; / the super block for drum
  3101                              <1> 	;cmp	word [cdev], 0
  3102 0000534D 803D[7F6E0000]00    <1> 	cmp	byte [cdev], 0
  3103                              <1> 		; tst cdev / is the device the disk
  3104 00005354 7606                <1> 	jna	short imap2
  3105                              <1> 		; beq 1f / yes
  3106 00005356 81C608020000        <1> 	add	esi, mount - systm
  3107                              <1> 		; add $mount-systm,r2 / for mounted device,
  3108                              <1> 			; / r2 points to 1st word of its super block
  3109                              <1> imap2: ; 1:
  3110 0000535C 66031E              <1> 	add	bx, [esi] ;; add free map size to si
  3111                              <1> 		; add (r2)+,(sp) / get byte address of allocation bit
  3112 0000535F 6683C304            <1> 	add	bx, 4
  3113 00005363 01F3                <1> 	add	ebx, esi
  3114                              <1>         	; add (sp)+,r2 / ?
  3115                              <1> 	;add	ebx, 4 ;; inode map offset in superblock
  3116                              <1> 		      ;; (2 + free map size + 2)
  3117                              <1> 		; add $2,r2 / ?
  3118                              <1> 
  3119                              <1> 	; 11/02/2022
  3120 00005365 81C68B010000        <1> 	add	esi, eofitab-1 ; last byte of the inode table in sb
  3121 0000536B 39DE                <1> 	cmp	esi, ebx  ; cf will be 1
  3122                              <1> 			  ; if inode num overs inode count
  3123                              <1> 
  3124                              <1>  	; DL/DX (MQ) has a 1 in the calculated bit position
  3125                              <1>         ; BX (R2) has byte address of the byte with allocation bit
  3126                              <1> 
  3127                              <1> 	; 11/02/2022
  3128                              <1> 	; if ebx > last byte of the inode table --> cf = 1
  3129                              <1> 	;	(number of requested inode > inode count)
  3130                              <1> 
  3131 0000536D C3                  <1> 	retn
  3132                              <1> 		; rts r0
  2101                                  %include 'u6.s'        ; 31/05/2015
  2102                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS6.INC
  2103                              <1> ; Last Modification: 03/02/2022
  2104                              <1> ; ----------------------------------------------------------------------------
  2105                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2106                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2107                              <1> ;
  2108                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2109                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2110                              <1> ; <Bell Laboratories (17/3/1972)>
  2111                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2112                              <1> ;
  2113                              <1> ; Retro UNIX 8086 v1 - U6.ASM (23/07/2014) //// UNIX v1 -> u6.s
  2114                              <1> ;
  2115                              <1> ; ****************************************************************************
  2116                              <1> 
  2117                              <1> readi:
  2118                              <1> 	; 11/01/2022
  2119                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2120                              <1> 	; 20/05/2015
  2121                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2122                              <1> 	; 11/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2123                              <1> 	;
  2124                              <1> 	; Reads from an inode whose number in R1
  2125                              <1> 	; 
  2126                              <1> 	; INPUTS ->
  2127                              <1> 	;    r1 - inode number
  2128                              <1> 	;    u.count - byte count user desires
  2129                              <1> 	;    u.base - points to user buffer
  2130                              <1> 	;    u.fofp - points to word with current file offset
  2131                              <1> 	; OUTPUTS ->
  2132                              <1> 	;    u.count - cleared
  2133                              <1> 	;    u.nread - accumulates total bytes passed back
  2134                              <1> 	;
  2135                              <1> 	; ((AX = R1)) input/output
  2136                              <1> 	;    (Retro UNIX Prototype : 01/03/2013 - 14/12/2012, UNIXCOPY.ASM)
  2137                              <1>         ;    ((Modified registers: edx, ebx, ecx, esi, esi, ebp))  
  2138                              <1> 
  2139 0000536E 31D2                <1> 	xor	edx, edx ; 0
  2140 00005370 8915[C06E0000]      <1> 	mov 	[u.nread], edx ; 0
  2141                              <1> 		 ; clr u.nread / accumulates number of bytes transmitted
  2142 00005376 668915[FD6E0000]    <1> 	mov	[u.pcount], dx ; 19/05/2015
  2143 0000537D 3915[BC6E0000]      <1> 	cmp 	[u.count], edx ; 0
  2144                              <1> 	         ; tst u.count / is number of bytes to be read greater than 0
  2145 00005383 7701                <1> 	ja 	short readi_1 ; 1f
  2146                              <1> 		 ; bgt 1f / yes, branch
  2147 00005385 C3                  <1> 	retn
  2148                              <1> 		 ; rts r0 / no, nothing to read; return to caller
  2149                              <1> readi_1: ; 1:
  2150                              <1> 	         ; mov r1,-(sp) / save i-number on stack
  2151 00005386 6683F828            <1> 	cmp	ax, 40
  2152                              <1> 		 ; cmp r1,$40. / want to read a special file 
  2153                              <1> 		 ;             / (i-nodes 1,...,40 are for special files)
  2154                              <1>         ;ja	dskr 
  2155                              <1> 		 ; ble 1f / yes, branch
  2156                              <1> 		 ; jmp dskr / no, jmp to dskr; 
  2157                              <1> 		 ;         / read file with i-node number (r1)
  2158                              <1> 		 ;    / starting at byte ((u.fofp)), read in u.count bytes
  2159                              <1> 	; 24/12/2021
  2160 0000538A 7605                <1> 	jna	short readi_3
  2161 0000538C E9CF000000          <1> 	jmp	dskr
  2162                              <1> readi_3:
  2163                              <1> 	; (20/05/2015)
  2164 00005391 50                  <1> 	push	eax ; because subroutines will jump to 'ret_'
  2165                              <1> 	; 1:
  2166 00005392 0FB6D8              <1> 	movzx	ebx, al
  2167                              <1> 	; 11/01/2022
  2168 00005395 C1E302              <1> 	shl	ebx, 2
  2169                              <1> 	;shl	bx, 2
  2170                              <1> 		 ; asl r1 / multiply inode number by 2
  2171 00005398 81C3[9C530000]      <1> 	add	ebx, readi_2 - 4
  2172 0000539E FF23                <1> 	jmp	dword [ebx]	
  2173                              <1> 		 ; jmp *1f-2(r1)
  2174                              <1> readi_2: ; 1:
  2175 000053A0 [EC530000]          <1> 	dd	rtty ; tty, AX = 1 (runix)
  2176                              <1> 		 ;rtty / tty; r1=2
  2177                              <1> 		 ;rppt / ppt; r1=4
  2178 000053A4 [3C540000]          <1> 	dd	rmem ; mem, AX = 2 (runix)
  2179                              <1> 		 ;rmem / mem; r1=6
  2180                              <1> 		 ;rrf0 / rf0
  2181                              <1> 		 ;rrk0 / rk0
  2182                              <1> 		 ;rtap / tap0
  2183                              <1> 		 ;rtap / tap1
  2184                              <1> 		 ;rtap / tap2
  2185                              <1> 		 ;rtap / tap3
  2186                              <1> 		 ;rtap / tap4
  2187                              <1> 		 ;rtap / tap5
  2188                              <1> 		 ;rtap / tap6
  2189                              <1> 		 ;rtap / tap7
  2190 000053A8 [275B0000]          <1> 	dd	rfd ; fd0, AX = 3 (runix only)
  2191 000053AC [275B0000]          <1> 	dd	rfd ; fd1, AX = 4 (runix only)
  2192 000053B0 [275B0000]          <1> 	dd	rhd ; hd0, AX = 5 (runix only)
  2193 000053B4 [275B0000]          <1> 	dd	rhd ; hd1, AX = 6 (runix only)	
  2194 000053B8 [275B0000]          <1> 	dd	rhd ; hd2, AX = 7 (runix only)
  2195 000053BC [275B0000]          <1> 	dd	rhd ; hd3, AX = 8 (runix only)	
  2196 000053C0 [51540000]          <1> 	dd	rlpr ; lpr, AX = 9 (invalid, write only device !?)
  2197 000053C4 [38540000]          <1> 	dd	rcvt ; tty0, AX = 10 (runix)	  
  2198                              <1> 		 ;rcvt / tty0
  2199 000053C8 [38540000]          <1> 	dd	rcvt ; tty1, AX = 11 (runix)	  
  2200                              <1> 		 ;rcvt / tty1
  2201 000053CC [38540000]          <1> 	dd	rcvt ; tty2, AX = 12 (runix)	  
  2202                              <1> 		 ;rcvt / tty2
  2203 000053D0 [38540000]          <1> 	dd	rcvt ; tty3, AX = 13 (runix)	  
  2204                              <1> 		 ;rcvt / tty3
  2205 000053D4 [38540000]          <1> 	dd	rcvt ; tty4, AX = 14 (runix)	  
  2206                              <1> 		 ;rcvt / tty4
  2207 000053D8 [38540000]          <1> 	dd	rcvt ; tty5, AX = 15 (runix)	  
  2208                              <1> 		 ;rcvt / tty5
  2209 000053DC [38540000]          <1> 	dd	rcvt ; tty6, AX = 16 (runix)	  
  2210                              <1> 		 ;rcvt / tty6
  2211 000053E0 [38540000]          <1> 	dd	rcvt ; tty7, AX = 17 (runix)	  
  2212                              <1> 		 ;rcvt / tty7
  2213 000053E4 [38540000]          <1> 	dd	rcvt ; COM1, AX = 18 (runix only)	  
  2214                              <1> 		 ;rcrd / crd
  2215 000053E8 [38540000]          <1> 	dd	rcvt ; COM2, AX = 19 (runix only)
  2216                              <1> 
  2217                              <1> rtty: ; / read from console tty
  2218                              <1> 	; 11/01/2022
  2219                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2220                              <1> 	; 17/10/2015 - 16/07/2015 (Retro UNIX 8086 v1)
  2221                              <1> 	; 	     (Only 1 byte is read, by ignoring byte count!)
  2222                              <1> 	;  	     WHAT FOR: Every character from Keyboard input 
  2223                              <1> 	;	     must be written immediate on video page (screen)
  2224                              <1> 	;	     when it is required.	
  2225                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2226                              <1> 	; 11/03/2013 - 19/06/2014 (Retro UNIX 8086 v1)
  2227                              <1> 	;
  2228                              <1> 	; Console tty buffer is PC keyboard buffer
  2229                              <1> 	; and keyboard-keystroke handling is different than original
  2230                              <1> 	; unix (PDP-11) here. TTY/Keyboard procedures here are changed
  2231                              <1> 	; according to IBM PC compatible ROM BIOS keyboard functions. 
  2232                              <1> 	;
  2233                              <1> 	; 06/12/2013
  2234 000053EC 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2235 000053F3 8A83[F76B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2236                              <1> rttys:
  2237                              <1> 		; mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
  2238                              <1> 	               ; / of the control and status block
  2239                              <1> 		; tst 2(r5) / for the console tty; this word points to the console
  2240                              <1> 		       ; / tty buffer
  2241                              <1> 	; 28/07/2013
  2242 000053F9 A2[EC6E0000]        <1> 	mov 	[u.ttyn], al
  2243                              <1> 	; 13/01/2014
  2244 000053FE FEC0                <1> 	inc	al
  2245 00005400 A2[C86E0000]        <1> 	mov	[u.ttyp], al ; tty number + 1
  2246                              <1> rtty_nc: ; 01/02/2014
  2247                              <1> 	; 29/09/2013
  2248                              <1> 	;mov	ecx, 10
  2249                              <1> 	; 11/01/2022
  2250 00005405 29C9                <1> 	sub	ecx, ecx
  2251 00005407 B10A                <1> 	mov	cl, 10
  2252                              <1> rtty_1: 	; 01/02/2014
  2253                              <1> 	;push 	cx ; 29/09/2013
  2254                              <1> 	; 24/12/2021
  2255 00005409 51                  <1> 	push	ecx
  2256                              <1> 	; byte [u.ttyn] = tty number (0 to 9) 
  2257 0000540A B001                <1> 	mov 	al, 1
  2258 0000540C E8660B0000          <1> 	call 	getc
  2259                              <1> 	; 24/12/2021
  2260 00005411 59                  <1> 	pop	ecx
  2261                              <1> 	;pop 	cx ; 29/09/2013	
  2262 00005412 7516                <1> 	jnz	short rtty_2
  2263                              <1> 		; bne 1f / 2nd word of console tty buffer contains number
  2264                              <1> 	               ; / of chars. Is this number non-zero?
  2265 00005414 E20D                <1> 	loop	rtty_idle ; 01/02/2014
  2266                              <1> 	; 05/10/2013
  2267 00005416 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn]
  2268                              <1> 	; 29/09/2013
  2269 0000541C E898FBFFFF          <1> 	call	sleep
  2270                              <1> 		; jsr r0,canon; ttych / if 0, call 'canon' to get a line
  2271                              <1>                 ;           / (120 chars.)
  2272                              <1> 	;byte [u.ttyn] = tty number (0 to 9) 
  2273 00005421 EBE2                <1> 	jmp	short rtty_nc ; 01/02/2014
  2274                              <1> 
  2275                              <1> rtty_idle:
  2276                              <1> 	; 29/07/2013
  2277 00005423 E804FBFFFF          <1> 	call 	idle
  2278 00005428 EBDF                <1> 	jmp	short rtty_1 ; 01/02/2014
  2279                              <1> 	;1:
  2280                              <1> 		; tst 2(r5) / is the number of characters zero
  2281                              <1> 		; beq ret1 / yes, return to caller via 'ret1'
  2282                              <1> 		; movb *4(r5),r1 / no, put character in r1
  2283                              <1> 		; inc 4(r5) / 3rd word of console tty buffer points to byte which
  2284                              <1> 		          ; / contains the next char.
  2285                              <1> 		; dec 2(r5) / decrement the character count
  2286                              <1> rtty_2:
  2287 0000542A 30C0                <1> 	xor 	al, al
  2288 0000542C E8460B0000          <1> 	call 	getc
  2289 00005431 E892000000          <1> 	call	passc
  2290                              <1> 		; jsr r0,passc / move the character to core (user)
  2291                              <1> 	;; 17/10/2015 - 16/07/2015
  2292                              <1> 	; 19/06/2014
  2293                              <1> 	;;jnz	short rtty_nc
  2294 00005436 58                  <1> 	pop	eax  ; (20/05/2015)
  2295 00005437 C3                  <1> 	retn 
  2296                              <1> ;ret1:
  2297                              <1> 		; jmp ret / return to caller via 'ret'
  2298                              <1> 
  2299                              <1> rcvt:   ; < receive/read character from tty >
  2300                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2301                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2302                              <1> 	;
  2303                              <1> 	; Retro UNIX 8086 v1 modification !
  2304                              <1> 	; 
  2305                              <1> 	; In original UNIX v1, 'rcvt' routine 
  2306                              <1> 	;		(exactly different than this one)
  2307                              <1> 	;	was in 'u9.s' file.
  2308                              <1> 	;
  2309 00005438 2C0A                <1> 	sub 	al, 10
  2310                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2311                              <1> 	; 16/07/2013
  2312                              <1> 	; 21/05/2013
  2313 0000543A EBBD                <1>         jmp     short rttys
  2314                              <1>       
  2315                              <1> ;rppt: / read paper tape
  2316                              <1> ;	jsr	r0,pptic / gets next character in clist for ppt input and
  2317                              <1> ;			 / places
  2318                              <1> ;		br ret / it in r1; if there 1s no problem with reader, it
  2319                              <1> ;		       / also enables read bit in prs
  2320                              <1> ;	jsr	r0,passc / place character in users buffer area
  2321                              <1> ;	br	rppt
  2322                              <1> 
  2323                              <1> rmem: ; / transfer characters from memory to a user area of core
  2324                              <1> 	; 17/10/2015
  2325                              <1> 	; 11/06/2015
  2326                              <1> 	; 24/05/2015
  2327                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2328                              <1> 	;
  2329 0000543C 8B35[A86E0000]      <1> 	mov     esi, [u.fofp]
  2330                              <1> rmem_1:
  2331 00005442 8B1E                <1>         mov     ebx, [esi]        
  2332                              <1> 	        ; mov *u.fofp,r1 / save file offset which points to the char
  2333                              <1> 		               ; / to be transferred to user
  2334 00005444 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2335                              <1> 		; inc *u.fofp / increment file offset to point to 'next' 
  2336                              <1> 			    ; / char in memory file
  2337 00005446 8A03                <1> 	mov	al, [ebx]
  2338                              <1> 		; movb (r1),r1 / get character from memory file, 
  2339                              <1> 		             ; / put it in r1
  2340 00005448 E87B000000          <1> 	call	passc        ; jsr r0,passc / move this character to 
  2341                              <1> 			     ;  / the next byte of the users core area
  2342                              <1> 		; br rmem / continue
  2343 0000544D 75F3                <1> 	jnz	short rmem_1
  2344                              <1> ret_:
  2345 0000544F 58                  <1> 	pop	eax ; 09/06/2015
  2346 00005450 C3                  <1> 	retn
  2347                              <1> 
  2348                              <1> rlpr:
  2349                              <1> ;1:
  2350                              <1> ;rcrd:
  2351 00005451 C705[ED6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2351 00005459 0000                <1>
  2352 0000545B E972E6FFFF          <1> 	jmp	error
  2353                              <1> 		;jmp	error / see 'error' routine
  2354                              <1> 
  2355                              <1> dskr:
  2356                              <1> 	; 12/10/2015
  2357                              <1> 	; 21/08/2015
  2358                              <1> 	; 25/07/2015
  2359                              <1> 	; 10/07/2015
  2360                              <1> 	; 16/06/2015
  2361                              <1> 	; 31/05/2015
  2362                              <1> 	; 24/05/2015 (Retro UNIX 386 v1 - Beginning)
  2363                              <1> 	; 26/04/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2364                              <1> dskr_0:
  2365 00005460 50                  <1> 	push	eax
  2366                              <1> 		; mov (sp),r1 / i-number in r1
  2367                              <1> 	; AX = i-number
  2368 00005461 E834FDFFFF          <1> 	call	iget
  2369                              <1> 		; jsr r0,iget / get i-node (r1) into i-node section of core
  2370 00005466 0FB715[9C6B0000]    <1>         movzx   edx, word [i.size] ; 16/06/2015
  2371                              <1> 		; mov i.size,r2 / file size in bytes in r2
  2372 0000546D 8B1D[A86E0000]      <1> 	mov	ebx, [u.fofp]
  2373 00005473 2B13                <1> 	sub	edx, [ebx]
  2374                              <1> 		; sub *u.fofp,r2 / subtract file offset
  2375                              <1>         ; 12/10/2015
  2376                              <1> 	; jna     short ret_ 
  2377                              <1> 		; blos ret
  2378 00005475 7709                <1> 	ja	short dskr_1
  2379                              <1> 	;
  2380                              <1> dskr_retn: ; 12/10/2015
  2381 00005477 58                  <1> 	pop	eax
  2382 00005478 C605[FF6E0000]00    <1> 	mov	byte [u.kcall], 0
  2383 0000547F C3                  <1> 	retn	
  2384                              <1> dskr_1: 
  2385 00005480 3B15[BC6E0000]      <1> 	cmp     edx, [u.count] 
  2386                              <1> 		; cmp r2,u.count / are enough bytes left in file 
  2387                              <1> 			       ; / to carry out read
  2388 00005486 7306                <1> 	jnb	short dskr_2
  2389                              <1> 		; bhis 1f
  2390 00005488 8915[BC6E0000]      <1> 	mov	[u.count], edx
  2391                              <1> 		; mov r2,u.count / no, just read to end of file
  2392                              <1> dskr_2: ; 1:
  2393                              <1> 	; AX = i-number
  2394 0000548E E89EFBFFFF          <1> 	call	mget
  2395                              <1> 		; jsr r0,mget / returns physical block number of block 
  2396                              <1> 			    ; / in file where offset points
  2397                              <1> 	; eAX = physical block number
  2398 00005493 E8DE070000          <1> 	call	dskrd
  2399                              <1> 		; jsr r0,dskrd / read in block, r5 points to 
  2400                              <1> 			     ; / 1st word of data in buffer
  2401                              <1> 	; 09/06/2015
  2402 00005498 803D[FF6E0000]00    <1> 	cmp	byte [u.kcall], 0 ; the caller is 'namei' sign (=1)
  2403 0000549F 770F                <1> 	ja	short dskr_4	  ; zf=0 -> the caller is 'namei'
  2404 000054A1 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0
  2405 000054A9 7705                <1> 	ja	short dskr_4
  2406                              <1> dskr_3:
  2407                              <1> 	; [u.base] = virtual address to transfer (as destination address)
  2408 000054AB E853000000          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2409                              <1> dskr_4:
  2410                              <1> 	; eBX (r5) = system (I/O) buffer address -physical-
  2411 000054B0 E8BC020000          <1> 	call	sioreg
  2412                              <1> 		; jsr r0,sioreg
  2413 000054B5 87F7                <1> 	xchg	esi, edi
  2414                              <1> 	; eDI = file (user data) offset
  2415                              <1> 	; eSI = sector (I/O) buffer offset
  2416                              <1> 	; eCX = byte count
  2417 000054B7 F3A4                <1> 	rep	movsb
  2418                              <1> 		; movb (r2)+,(r1)+ / move data from buffer into working core
  2419                              <1> 		                 ; / starting at u.base
  2420                              <1> 		; dec r3
  2421                              <1> 		; bne 2b / branch until proper number of bytes are transferred
  2422                              <1> 	; 25/07/2015
  2423                              <1> 	; eax = remain bytes in buffer
  2424                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2425 000054B9 09C0                <1> 	or	eax, eax
  2426 000054BB 75EE                <1> 	jnz	short dskr_3 ; (page end before system buffer end!)		
  2427                              <1> 	; 03/08/2013
  2428                              <1> 	;pop	eax
  2429 000054BD 390D[BC6E0000]      <1> 	cmp	[u.count], ecx ; 0
  2430                              <1> 		; tst u.count / all bytes read off disk
  2431                              <1> 		; bne dskr
  2432                              <1> 		; br ret
  2433                              <1>         ;ja	short dskr_0
  2434                              <1> 	;mov	[u.kcall], cl ; 0 ; 09/06/2015
  2435                              <1> 	;retn
  2436                              <1> 	; 12/10/2015
  2437 000054C3 76B2                <1> 	jna	short dskr_retn
  2438 000054C5 58                  <1> 	pop	eax  ; (i-node number)
  2439 000054C6 EB98                <1> 	jmp	short dskr_0
  2440                              <1> 	
  2441                              <1> passc:
  2442                              <1> 	; 18/10/2015
  2443                              <1> 	; 10/07/2015
  2444                              <1> 	; 01/07/2015
  2445                              <1> 	; 08/06/2015
  2446                              <1> 	; 04/06/2015
  2447                              <1> 	; 20/05/2015
  2448                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2449                              <1> 	;
  2450                              <1>    	;(Retro UNIX 386 v1 - translation from user's virtual address
  2451                              <1> 	;		      to physical address
  2452 000054C8 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2453                              <1> 			     ; 1-4095 --> use previous physical base address
  2454                              <1> 			     ; in [u.pbase]
  2455 000054D0 7705                <1> 	ja	short passc_3
  2456                              <1> 	; 08/06/2015 - 10/07/2015
  2457 000054D2 E82C000000          <1> 	call	trans_addr_w
  2458                              <1> passc_3:
  2459                              <1> 	; 19/05/2015
  2460 000054D7 66FF0D[FD6E0000]    <1> 	dec	word [u.pcount]
  2461                              <1> 	;
  2462 000054DE 8B1D[F96E0000]      <1> 	mov	ebx, [u.pbase]
  2463 000054E4 8803                <1> 	mov	[ebx], al
  2464                              <1> 		; movb r1,*u.base / move a character to the next byte of the
  2465                              <1> 		               ; / users buffer
  2466 000054E6 FF05[B86E0000]      <1> 	inc	dword [u.base]
  2467                              <1> 		; inc u.base / increment the pointer to point to 
  2468                              <1> 			  ; / the next byte in users buffer
  2469 000054EC FF05[F96E0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  2470 000054F2 FF05[C06E0000]      <1> 	inc	dword [u.nread]
  2471                              <1> 		; inc u.nread / increment the number of bytes read
  2472 000054F8 FF0D[BC6E0000]      <1> 	dec	dword [u.count]
  2473                              <1> 		; dec u.count / decrement the number of bytes to be read
  2474                              <1> 		; bne 1f / any more bytes to read?; yes, branch
  2475 000054FE C3                  <1> 	retn
  2476                              <1> 		; mov (sp)+,r0 / no, do a non-local return to the caller of
  2477                              <1> 		             ; / 'readi' by:
  2478                              <1> 		;/ (1) pop the return address off the stack into r0
  2479                              <1> 		; mov (sp)+,r1 / (2) pop the i-number off the stack into r1
  2480                              <1> 	;1:
  2481                              <1> 		; clr	*$ps / clear processor status
  2482                              <1> 		; rts r0 / return to address currently on top of stack
  2483                              <1> 
  2484                              <1> trans_addr_r:
  2485                              <1> 	; Translate virtual address to physical address 
  2486                              <1> 	; for reading from user's memory space
  2487                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2488                              <1> 	; 18/10/2015
  2489                              <1> 	; 10/07/2015
  2490                              <1> 	; 09/06/2015
  2491                              <1> 	; 08/06/2015 
  2492                              <1> 	; 04/06/2015
  2493                              <1> 	;
  2494                              <1> 	; 18/10/2015
  2495 000054FF 31D2                <1> 	xor	edx, edx ; 0 (read access sign)
  2496 00005501 EB04                <1> 	jmp 	short trans_addr_rw
  2497                              <1> 
  2498                              <1> 	;push	eax
  2499                              <1> 	;push	ebx
  2500                              <1> 	;mov	ebx, [u.base]
  2501                              <1> 	;call	get_physical_addr ; get physical address
  2502                              <1> 	;;jnc	short cpass_0
  2503                              <1> 	;jnc	short passc_1
  2504                              <1> 	;mov	[u.error], eax
  2505                              <1> 	;;pop	ebx
  2506                              <1> 	;;pop	eax
  2507                              <1> 	;jmp	error
  2508                              <1> ;cpass_0:
  2509                              <1> 	; 18/10/2015
  2510                              <1> 	; 20/05/2015
  2511                              <1> 	;mov 	[u.pbase], eax ; physical address	
  2512                              <1> 	;mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2513                              <1> 	;pop	ebx
  2514                              <1> 	;pop	eax
  2515                              <1> 	;retn	; 08/06/2015
  2516                              <1> 
  2517                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2518                              <1> trans_addr_w:
  2519                              <1> 	; 31/12/2021
  2520                              <1> 	; Translate virtual address to physical address 
  2521                              <1> 	; for writing to user's memory space
  2522                              <1> 	; (Retro UNIX 386 v1 feature only !)
  2523                              <1> 	; 18/10/2015
  2524                              <1> 	; 29/07/2015
  2525                              <1> 	; 10/07/2015
  2526                              <1> 	; 09/06/2015
  2527                              <1> 	; 08/06/2015
  2528                              <1> 	; 04/06/2015 (passc)
  2529                              <1> 	;
  2530                              <1> 	; 18/10/2015
  2531 00005503 29D2                <1> 	sub	edx, edx
  2532 00005505 FEC2                <1> 	inc	dl ; 1 (write access sign)
  2533                              <1> trans_addr_rw:
  2534 00005507 50                  <1> 	push	eax
  2535 00005508 53                  <1> 	push	ebx
  2536                              <1> 	; 18/10/2015
  2537 00005509 52                  <1> 	push 	edx ; r/w sign (in DL)
  2538                              <1> 	;
  2539 0000550A 8B1D[B86E0000]      <1> 	mov	ebx, [u.base]
  2540 00005510 E88DDCFFFF          <1> 	call	get_physical_addr ; get physical address
  2541 00005515 730A                <1> 	jnc	short passc_0
  2542 00005517 A3[ED6E0000]        <1> 	mov	[u.error], eax
  2543                              <1> 	;pop	edx
  2544                              <1> 	;pop 	ebx
  2545                              <1> 	;pop	eax
  2546 0000551C E9B1E5FFFF          <1> 	jmp	error
  2547                              <1> passc_0:
  2548 00005521 F6C202              <1> 	test	dl, PTE_A_WRITE ; writable page ; 18/10/2015
  2549 00005524 5A                  <1> 	pop	edx ; 18/10/2015
  2550 00005525 7517                <1> 	jnz	short passc_1
  2551                              <1> 	; 18/10/2015
  2552 00005527 20D2                <1> 	and 	dl, dl
  2553 00005529 7413                <1> 	jz	short passc_1
  2554                              <1> 	; 20/05/2015
  2555                              <1> 	; read only (duplicated) page -must be copied to a new page-
  2556                              <1> 	; EBX = linear address
  2557 0000552B 51                  <1> 	push 	ecx
  2558 0000552C 53                  <1> 	push	ebx ; * ; 31/12/2021 (BugFix)
  2559 0000552D E8DFDBFFFF          <1> 	call 	copy_page
  2560 00005532 5B                  <1> 	pop	ebx ; * ; 31/12/2021 (BugFix)
  2561 00005533 59                  <1> 	pop	ecx
  2562 00005534 7217                <1> 	jc	short passc_2
  2563                              <1> 	; 24/12/2021
  2564                              <1> 	;push	eax ; physical address of the new/allocated page
  2565                              <1> 	;call	add_to_swap_queue
  2566                              <1> 	;pop	eax
  2567                              <1> 	; 18/10/2015
  2568 00005536 81E3FF0F0000        <1> 	and 	ebx, PAGE_OFF ; 0FFFh
  2569                              <1> 	;mov 	ecx, PAGE_SIZE
  2570                              <1> 	;sub	ecx, ebx 
  2571 0000553C 01D8                <1> 	add	eax, ebx  
  2572                              <1> passc_1: 
  2573                              <1> 	; 18/10/2015
  2574                              <1> 	; 20/05/2015
  2575 0000553E A3[F96E0000]        <1> 	mov 	[u.pbase], eax ; physical address	
  2576 00005543 66890D[FD6E0000]    <1> 	mov	[u.pcount], cx ; remain byte count in page (1-4096)
  2577 0000554A 5B                  <1> 	pop	ebx
  2578 0000554B 58                  <1> 	pop	eax
  2579 0000554C C3                  <1> 	retn	; 08/06/2015
  2580                              <1> passc_2:
  2581 0000554D C705[ED6E0000]0400- <1> 	mov	dword [u.error], ERR_MINOR_IM ; "Insufficient memory !" error
  2581 00005555 0000                <1>
  2582                              <1> 	;pop 	ebx
  2583                              <1> 	;pop	eax
  2584 00005557 E976E5FFFF          <1> 	jmp	error
  2585                              <1> 
  2586                              <1> writei:
  2587                              <1> 	; 03/02/2022
  2588                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2589                              <1> 	; 20/05/2015
  2590                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2591                              <1> 	; 12/03/2013 - 31/07/2013 (Retro UNIX 8086 v1)
  2592                              <1> 	;
  2593                              <1> 	; Write data to file with inode number in R1
  2594                              <1> 	; 
  2595                              <1> 	; INPUTS ->
  2596                              <1> 	;    r1 - inode number
  2597                              <1> 	;    u.count - byte count to be written
  2598                              <1> 	;    u.base - points to user buffer
  2599                              <1> 	;    u.fofp - points to word with current file offset
  2600                              <1> 	; OUTPUTS ->
  2601                              <1> 	;    u.count - cleared
  2602                              <1> 	;    u.nread - accumulates total bytes passed back	
  2603                              <1> 	; ((AX = R1))
  2604                              <1> 	;    (Retro UNIX Prototype : 18/11/2012 - 11/11/2012, UNIXCOPY.ASM)
  2605                              <1> 	;    ((Modified registers: DX, BX, CX, SI, DI, BP)) 	
  2606                              <1> 
  2607 0000555C 31C9                <1> 	xor	ecx, ecx
  2608 0000555E 890D[C06E0000]      <1> 	mov 	[u.nread], ecx  ; 0
  2609                              <1> 		; clr u.nread / clear the number of bytes transmitted during
  2610                              <1> 		            ; / read or write calls
  2611 00005564 66890D[FD6E0000]    <1> 	mov	[u.pcount], cx ; 19/05/2015
  2612 0000556B 390D[BC6E0000]      <1> 	cmp 	[u.count], ecx
  2613                              <1> 	;	; tst u.count / test the byte count specified by the user
  2614 00005571 7701                <1> 	ja 	short writei_1 ; 1f
  2615                              <1> 		; bgt 1f / any bytes to output; yes, branch
  2616 00005573 C3                  <1> 	retn
  2617                              <1> 	;	; rts r0 / no, return - no writing to do
  2618                              <1> writei_1: ;1:
  2619                              <1> 		; mov r1 ,-(sp) / save the i-node number on the stack
  2620 00005574 6683F828            <1> 	cmp 	ax, 40
  2621                              <1> 		; cmp r1,$40.
  2622                              <1> 		; / does the i-node number indicate a special file?
  2623                              <1> 	;ja	dskw 
  2624                              <1> 		; bgt dskw / no, branch to standard file output
  2625                              <1> 	; 24/12/2021
  2626 00005578 7605                <1> 	jna	short writei_3
  2627 0000557A E9ED000000          <1> 	jmp	dskw
  2628                              <1> writei_3:
  2629                              <1> 	; (20/05/2015)
  2630 0000557F 50                  <1> 	push	eax ; because subroutines will jump to 'wret'
  2631 00005580 0FB6D8              <1> 	movzx	ebx, al
  2632                              <1> 	; 03/02/2022
  2633 00005583 C1E302              <1> 	shl	ebx, 2
  2634                              <1> 	;shl	bx, 2
  2635                              <1> 		; asl r1 / yes, calculate the index into the special file
  2636 00005586 81C3[8A550000]      <1> 	add	ebx, writei_2 - 4
  2637 0000558C FF23                <1> 	jmp	dword [ebx]	
  2638                              <1> 		; jmp *1f-2(r1)
  2639                              <1> 		; / jump table and jump to the appropriate routine
  2640                              <1> writei_2: ;1:
  2641 0000558E [DA550000]          <1> 	dd	wtty ; tty, AX = 1 (runix)
  2642                              <1> 		 ;wtty / tty; r1=2
  2643                              <1> 		 ;wppt / ppt; r1=4
  2644 00005592 [3C560000]          <1> 	dd	wmem ; mem, AX = 2 (runix)
  2645                              <1> 		 ;wmem / mem; r1=6
  2646                              <1> 		 ;wrf0 / rf0
  2647                              <1> 		 ;wrk0 / rk0
  2648                              <1> 		 ;wtap / tap0
  2649                              <1> 		 ;wtap / tap1
  2650                              <1> 		 ;wtap / tap2
  2651                              <1> 		 ;wtap / tap3
  2652                              <1> 		 ;wtap / tap4
  2653                              <1> 		 ;wtap / tap5
  2654                              <1> 		 ;wtap / tap6
  2655                              <1> 		 ;wtap / tap7
  2656 00005596 [B05B0000]          <1> 	dd	wfd ; fd0, AX = 3 (runix only)
  2657 0000559A [B05B0000]          <1> 	dd	wfd ; fd1, AX = 4 (runix only)
  2658 0000559E [B05B0000]          <1> 	dd	whd ; hd0, AX = 5 (runix only)
  2659 000055A2 [B05B0000]          <1> 	dd	whd ; hd1, AX = 6 (runix only)	
  2660 000055A6 [B05B0000]          <1> 	dd	whd ; hd2, AX = 7 (runix only)
  2661 000055AA [B05B0000]          <1> 	dd	whd ; hd3, AX = 8 (runix only)	
  2662 000055AE [2D560000]          <1> 	dd	wlpr ; lpr, AX = 9   (runix)
  2663 000055B2 [27560000]          <1> 	dd	xmtt ; tty0, AX = 10 (runix)	  
  2664                              <1> 		 ;xmtt / tty0
  2665 000055B6 [27560000]          <1> 	dd	xmtt ; tty1, AX = 11 (runix)	  
  2666                              <1> 		 ;xmtt / tty1
  2667 000055BA [27560000]          <1> 	dd	xmtt ; tty2, AX = 12 (runix)	  
  2668                              <1> 		 ;xmtt / tty2
  2669 000055BE [27560000]          <1> 	dd	xmtt ; tty3, AX = 13 (runix)	  
  2670                              <1> 		 ;xmtt / tty3
  2671 000055C2 [27560000]          <1> 	dd	xmtt ; tty4, AX = 14 (runix)	  
  2672                              <1> 		 ;xmtt / tty4
  2673 000055C6 [27560000]          <1> 	dd	xmtt ; tty5, AX = 15 (runix)	  
  2674                              <1> 		 ;xmtt / tty5
  2675 000055CA [27560000]          <1> 	dd	xmtt ; tty6, AX = 16 (runix)	  
  2676                              <1> 		 ;xmtt / tty6
  2677 000055CE [27560000]          <1> 	dd	xmtt ; tty7, AX = 17 (runix)	  
  2678                              <1> 		 ;xmtt / tty7
  2679 000055D2 [27560000]          <1> 	dd	xmtt ; COM1, AX = 18 (runix only)	  
  2680                              <1> 		; / wlpr / lpr
  2681 000055D6 [27560000]          <1> 	dd	xmtt ; COM2, AX = 19 (runix only)	
  2682                              <1> 
  2683                              <1> wtty: ; write to console tty (write to screen)
  2684                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2685                              <1> 	; 18/11/2015
  2686                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2687                              <1> 	; 12/03/2013 - 07/07/2014 (Retro UNIX 8086 v1)
  2688                              <1> 	;
  2689                              <1> 	; Console tty output is on current video page
  2690                              <1> 	; Console tty character output procedure is changed here
  2691                              <1> 	; acconding to IBM PC compatible ROM BIOS video (text mode) functions.
  2692                              <1> 	;
  2693 000055DA 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2694 000055E1 8AA3[F76B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2695 000055E7 88E0                <1> 	mov	al, ah ; 07/07/2014
  2696                              <1> wttys:	
  2697                              <1> 	; 10/10/2013
  2698 000055E9 8825[EC6E0000]      <1> 	mov 	[u.ttyn], ah
  2699                              <1> 	; 13/01/2014
  2700 000055EF FEC0                <1> 	inc	al
  2701 000055F1 A2[C96E0000]        <1> 	mov	[u.ttyp+1], al ; tty number + 1
  2702                              <1> wtty_nc: ; 15/05/2013
  2703                              <1> 	; AH = [u.ttyn] = tty number ; 28/07/2013
  2704 000055F6 E816010000          <1> 	call	cpass
  2705                              <1> 		; jsr r0,cpass / get next character from user buffer area; if
  2706                              <1> 		             ; / none go to return address in syswrite
  2707                              <1> 		; tst r1 / is character = null
  2708                              <1> 		; beq wtty / yes, get next character
  2709                              <1> 	; 10/10/2013
  2710 000055FB 7428                <1> 	jz	short wret
  2711                              <1> 	;1 : 
  2712                              <1> 		;mov 	$240,*$ps / no, set processor priority to five
  2713                              <1> 		;cmpb	cc+1,$20. / is character count for console tty greater
  2714                              <1> 		;	          / than 20
  2715                              <1> 		;bhis	2f / yes; branch to put process to sleep
  2716                              <1> 	; 27/06/2014
  2717                              <1> wtty_1:
  2718                              <1> 	; AH = tty number
  2719                              <1> 	; AL = ASCII code of the character
  2720                              <1> 	; 15/04/2014
  2721                              <1> 	;push	ax
  2722                              <1> 	; 24/12/2021
  2723 000055FD 50                  <1> 	push	eax
  2724 000055FE E8E2090000          <1> 	call	putc ; 14/05/2013
  2725 00005603 731D                <1> 	jnc	short wtty_2
  2726                              <1> 	; 18/11/2015
  2727 00005605 E822F9FFFF          <1> 	call	idle
  2728                              <1> 	;mov	ax, [esp]
  2729                              <1> 	; 24/12/2021
  2730 0000560A 8B0424              <1> 	mov	eax, [esp]
  2731 0000560D E8D3090000          <1> 	call	putc
  2732 00005612 730E                <1> 	jnc	short wtty_2 
  2733                              <1> 	; 02/06/2014
  2734 00005614 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn]
  2735 0000561A E89AF9FFFF          <1> 	call	sleep
  2736                              <1> 	;pop	ax
  2737                              <1> 	; 24/12/2021
  2738 0000561F 58                  <1> 	pop	eax
  2739 00005620 EBDB                <1> 	jmp 	short wtty_1
  2740                              <1> 		; jc 	error ; 15/05/2013 (COM1 or COM2 serial port error)
  2741                              <1> 		; jsr 	r0,putc; 1 / find place in freelist to assign to 
  2742                              <1> 			      ; / console tty and
  2743                              <1> 		; br 	2f / place character in list; if none available
  2744                              <1> 		   	  ; / branch to put process to sleep
  2745                              <1> 		; jsr	r0,startty / attempt to output character on tty
  2746                              <1> wtty_2:
  2747                              <1> 	; 15/04/2014
  2748                              <1> 	;pop	ax
  2749                              <1> 	; 24/12/2021
  2750 00005622 58                  <1> 	pop	eax
  2751 00005623 EBD1                <1> 	jmp	short wtty_nc
  2752                              <1> 		; br wtty
  2753                              <1> wret:	; 10/10/2013 (20/05/2015)
  2754 00005625 58                  <1> 	pop	eax
  2755 00005626 C3                  <1> 	retn
  2756                              <1> 	;2:
  2757                              <1> 		;mov	r1,-(sp) / place character on stack
  2758                              <1> 		;jsr	r0,sleep; 1 / put process to sleep
  2759                              <1> 		;mov	(sp)+,r1 / remove character from stack
  2760                              <1> 		;br	1b / try again to place character in clist and output
  2761                              <1> 
  2762                              <1> xmtt:   ; < send/write character to tty >
  2763                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2764                              <1> 	; 15/05/2013 - 06/12/2013 (Retro UNIX 8086 v1)
  2765                              <1> 	;
  2766                              <1> 	; Retro UNIX 8086 v1 modification !
  2767                              <1> 	; 
  2768                              <1> 	; In original UNIX v1, 'xmtt' routine 
  2769                              <1> 	;		(exactly different than this one)
  2770                              <1> 	;	was in 'u9.s' file.
  2771                              <1> 	;
  2772 00005627 2C0A                <1> 	sub 	al, 10
  2773                              <1> 	; AL = tty number (0 to 9), (COM1=8, COM2=9)
  2774                              <1> 	; 10/10/2013
  2775 00005629 88C4                <1> 	mov	ah, al
  2776                              <1> 	; 28/07/2013
  2777 0000562B EBBC                <1> 	jmp	short wttys
  2778                              <1> 
  2779                              <1> ;wppt:
  2780                              <1> ;	jsr	r0,cpass / get next character from user buffer area,
  2781                              <1> ;		         / if none return to writei's calling routine
  2782                              <1> ;	jsr	r0,pptoc / output character on ppt
  2783                              <1> ;	br	wppt
  2784                              <1> wlpr:
  2785 0000562D C705[ED6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY ; 19/05/2015
  2785 00005635 0000                <1>
  2786 00005637 E996E4FFFF          <1> 	jmp 	error   ; ... Printing procedure will be located here ...
  2787                              <1> 		;/	jsr	r0,cpass
  2788                              <1> 		;/	cmp	r0,$'a
  2789                              <1> 		;/	blo	1f
  2790                              <1> 		;/	cmp	r1,$'z
  2791                              <1> 		;/	bhi	1f
  2792                              <1> 		;/	sub	$40,r1
  2793                              <1> 		;/1:
  2794                              <1> 		;/	jsr	r0,lptoc
  2795                              <1> 		;/	br	wlpr
  2796                              <1> 		; br rmem / continue
  2797                              <1> 
  2798                              <1> wmem: ; / transfer characters from a user area of core to memory file
  2799                              <1> 	; 17/10/2015
  2800                              <1> 	; 11/06/2015
  2801                              <1> 	; 24/05/2015
  2802                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2803                              <1> 	;
  2804 0000563C 813D[11070000]-     <1> 	cmp	dword [x_timer], clock ; multi tasking clock/timer
  2804 00005642 [4F4F0000]          <1>
  2805 00005646 7415                <1>         je      short wmem_acc_err
  2806                              <1> 	;
  2807 00005648 8B35[A86E0000]      <1>         mov     esi, [u.fofp] 
  2808                              <1> wmem_1:
  2809 0000564E E8BE000000          <1> 	call	cpass
  2810                              <1> 		; jsr r0,cpass / get next character from users area of
  2811                              <1> 			     ; / core and put it in r1
  2812                              <1>         	; mov r1,-(sp) / put character on the stack
  2813                              <1> 	; 20/09/2013
  2814 00005653 74D0                <1> 	jz	short wret ; wmem_2  
  2815 00005655 8B1E                <1>         mov     ebx, [esi]
  2816                              <1> 		; mov *u.fofp,r1 / save file offset in r1
  2817 00005657 FF06                <1>         inc     dword [esi] ; 17/10/2015
  2818                              <1> 		; inc *u.fofp / increment file offset to point to next
  2819                              <1> 			    ; / available location in file
  2820 00005659 8803                <1> 	mov	[ebx], al	
  2821                              <1> 		; movb (sp)+,(r1) / pop char off stack, put in memory loc 
  2822                              <1> 			        ; / assigned to it
  2823 0000565B EBF1                <1> 	jmp	short wmem_1
  2824                              <1> 		; br wmem / continue
  2825                              <1> 	;1:
  2826                              <1> 	;jmp	error / ?
  2827                              <1> ;wmem_2:	
  2828                              <1> ;	; 20/09/2013
  2829                              <1> ;	pop	ax
  2830                              <1> ;	retn
  2831                              <1> 
  2832                              <1> wmem_acc_err:
  2833 0000565D C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2833 00005665 0000                <1>
  2834 00005667 E966E4FFFF          <1> 	jmp	error
  2835                              <1> 
  2836                              <1> 
  2837                              <1> dskw: ; / write routine for non-special files
  2838                              <1> 	;
  2839                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2840                              <1> 	; 25/07/2015
  2841                              <1> 	; 16/06/2015
  2842                              <1> 	; 09/06/2015
  2843                              <1> 	; 31/05/2015 (Retro UNIX 386 v1 - Beginning)
  2844                              <1> 	; 26/04/2013 - 20/09/2013 (Retro UNIX 8086 v1)
  2845                              <1> 	;
  2846                              <1> 	; 01/08/2013 (mkdir_w check)
  2847                              <1> 
  2848                              <1> 	;push	ax ; 26/04/2013
  2849                              <1> 		; mov (sp),r1 / get an i-node number from the stack into r1
  2850                              <1> 	; 24/12/2021
  2851 0000566C 50                  <1> 	push	eax
  2852                              <1> 	; AX = inode number
  2853 0000566D E828FBFFFF          <1> 	call	iget
  2854                              <1> 		; jsr r0,iget / write i-node out (if modified), 
  2855                              <1> 		            ; / read i-node 'r1' into i-node area of core
  2856 00005672 8B1D[A86E0000]      <1>         mov     ebx, [u.fofp] 
  2857 00005678 8B13                <1> 	mov 	edx, [ebx]
  2858                              <1> 		; mov *u.fofp,r2 / put the file offset [(u.off) or the offset
  2859                              <1> 			       ; / in the fsp entry for this file] in r2
  2860 0000567A 0315[BC6E0000]      <1> 	add 	edx, [u.count]	
  2861                              <1> 		; add u.count,r2 / no. of bytes to be written
  2862                              <1> 			       ; / + file offset is put in r2
  2863                              <1> 	; 16/06/2015        
  2864 00005680 81FAFFFF0000        <1> 	cmp	edx, 65535 ; file size limit (for UNIX v1 file system)
  2865 00005686 760F                <1> 	jna	short dskw_0
  2866 00005688 C705[ED6E0000]1400- <1> 	mov	dword [u.error], ERR_FILE_SIZE ; 'file size error !'
  2866 00005690 0000                <1>
  2867 00005692 E93BE4FFFF          <1> 	jmp	error
  2868                              <1> dskw_0:	
  2869 00005697 663B15[9C6B0000]    <1> 	cmp     dx, [i.size]
  2870                              <1> 		; cmp r2,i.size / is this greater than the present size of
  2871                              <1> 		              ; / the file?
  2872 0000569E 760C                <1> 	jna	short dskw_1
  2873                              <1> 		; blos 1f / no, branch
  2874 000056A0 668915[9C6B0000]    <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 000056A7 E8F8FBFFFF          <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 000056AC E880F9FFFF          <1> 	call	mget
  2883                              <1> 	; eAX = Block number
  2884                              <1> 		; jsr r0,mget / get the block no. in which to write 
  2885                              <1> 			    ; /	the next data byte
  2886                              <1> 	; eax = block number
  2887 000056B1 8B1D[A86E0000]      <1> 	mov     ebx, [u.fofp]
  2888 000056B7 8B13                <1> 	mov	edx, [ebx]
  2889 000056B9 81E2FF010000        <1> 	and	edx, 1FFh  
  2890                              <1> 		; bit *u.fofp,$777 / test the lower 9 bits of the file offset
  2891 000056BF 750C                <1> 	jnz	short dskw_2
  2892                              <1> 		; bne 2f / if its non-zero, branch; if zero, file offset = 0,
  2893                              <1> 		       ; / 512, 1024,...(i.e., start of new block)
  2894 000056C1 813D[BC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2894 000056C9 0000                <1>
  2895                              <1> 		; cmp u.count,$512. / if zero, is there enough data to fill
  2896                              <1> 				  ; / an entire block? (i.e., no. of
  2897 000056CB 7305                <1> 	jnb	short dskw_3
  2898                              <1> 		; bhis 3f / bytes to be written greater than 512.? 
  2899                              <1> 			; / Yes, branch. Don't have to read block
  2900                              <1> dskw_2: ; 2: / in as no past info. is to be saved (the entire block will be
  2901                              <1>    		; / overwritten).
  2902 000056CD E8A4050000          <1> 	call	dskrd
  2903                              <1> 		; jsr r0,dskrd / no, must retain old info.. 
  2904                              <1> 			     ; / Hence, read block 'r1' into an I/O buffer
  2905                              <1> dskw_3: ; 3:
  2906                              <1> 	; eAX (r1) = block/sector number
  2907 000056D2 E811060000          <1> 	call	wslot
  2908                              <1> 		; jsr r0,wslot / set write and inhibit bits in I/O queue, 
  2909                              <1> 			   ; / proc. status=0, r5 points to 1st word of data
  2910 000056D7 803D[FF6E0000]00    <1> 	cmp	byte [u.kcall], 0
  2911 000056DE 770F                <1> 	ja	short dskw_5 ; zf=0 -> the caller is 'mkdir'
  2912                              <1> 	;
  2913 000056E0 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0
  2914 000056E8 7705                <1> 	ja	short dskw_5
  2915                              <1> dskw_4:
  2916                              <1> 	; [u.base] = virtual address to transfer (as source address)
  2917 000056EA E810FEFFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2918                              <1> dskw_5:
  2919                              <1> 	; eBX (r5) = system (I/O) buffer address
  2920 000056EF E87D000000          <1> 	call	sioreg
  2921                              <1> 		; jsr r0,sioreg / r3 = no. of bytes of data, 
  2922                              <1> 			     ; / r1 = address of data, r2 points to location
  2923                              <1> 			     ; / in buffer in which to start writing data
  2924                              <1> 	; eSI = file (user data) offset
  2925                              <1> 	; eDI = sector (I/O) buffer offset
  2926                              <1> 	; eCX = byte count
  2927                              <1> 	;
  2928 000056F4 F3A4                <1>   	rep	movsb
  2929                              <1> 		; movb (r1 )+,(r2)+ 
  2930                              <1> 		         ; / transfer a byte of data to the I/O buffer
  2931                              <1> 		; dec r3 / decrement no. of bytes to be written
  2932                              <1> 		; bne 2b / have all bytes been transferred? No, branch
  2933                              <1> 	; 25/07/2015
  2934                              <1> 	; eax = remain bytes in buffer
  2935                              <1>         ;       (check if remain bytes in the buffer > [u.pcount])
  2936 000056F6 09C0                <1> 	or	eax, eax
  2937 000056F8 75F0                <1> 	jnz	short dskw_4 ; (page end before system buffer end!)	
  2938                              <1> dskw_6:
  2939 000056FA E805060000          <1> 	call	dskwr
  2940                              <1> 		; jsr r0,dskwr / yes, write the block and the i-node
  2941 000056FF 833D[BC6E0000]00    <1>         cmp     dword [u.count], 0
  2942                              <1> 		; tst u.count / any more data to write?
  2943 00005706 77A4                <1> 	ja	short dskw_1
  2944                              <1> 		; bne 1b / yes, branch
  2945                              <1> 	; 03/08/2013
  2946 00005708 C605[FF6E0000]00    <1> 	mov	byte [u.kcall], 0
  2947                              <1> 	; 20/09/2013 (;;)
  2948                              <1> 	;pop	ax
  2949                              <1> 	; 24/12/2021
  2950 0000570F 58                  <1> 	pop	eax
  2951 00005710 C3                  <1> 	retn
  2952                              <1> 	;;jmp 	short dskw_ret 
  2953                              <1> 	        ; jmp ret / no, return to the caller via 'ret'
  2954                              <1> 
  2955                              <1> cpass: ; / get next character from user area of core and put it in r1
  2956                              <1> 	; 18/10/2015
  2957                              <1> 	; 10/10/2015
  2958                              <1> 	; 10/07/2015
  2959                              <1> 	; 02/07/2015
  2960                              <1> 	; 01/07/2015
  2961                              <1> 	; 24/06/2015
  2962                              <1> 	; 08/06/2015
  2963                              <1> 	; 04/06/2015
  2964                              <1> 	; 20/05/2015
  2965                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  2966                              <1> 	;
  2967                              <1> 	; INPUTS -> 
  2968                              <1> 	;     [u.base] = virtual address in user area
  2969                              <1> 	;     [u.count] = byte count (max.)
  2970                              <1> 	;     [u.pcount] = byte count in page (0 = reset)		
  2971                              <1> 	; OUTPUTS -> 
  2972                              <1> 	;     AL = the character which is pointed by [u.base]
  2973                              <1> 	;     zf = 1 -> transfer count has been completed	
  2974                              <1>         ;
  2975                              <1> 	; ((Modified registers:  EAX, EDX, ECX))
  2976                              <1> 	;
  2977                              <1> 	;
  2978 00005711 833D[BC6E0000]00    <1> 	cmp 	dword [u.count], 0  ; 14/08/2013
  2979                              <1> 		; tst u.count / have all the characters been transferred
  2980                              <1> 			    ; / (i.e., u.count, # of chars. left
  2981 00005718 763F                <1> 	jna	short cpass_3
  2982                              <1> 		; beq 1f / to be transferred = 0?) yes, branch
  2983 0000571A FF0D[BC6E0000]      <1> 	dec	dword [u.count]
  2984                              <1> 		; dec u.count / no, decrement u.count
  2985                              <1>         ; 19/05/2015 
  2986                              <1> 	;(Retro UNIX 386 v1 - translation from user's virtual address
  2987                              <1> 	;		      to physical address
  2988 00005720 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0 ; byte count in page = 0 (initial value)
  2989                              <1> 			     ; 1-4095 --> use previous physical base address
  2990                              <1> 			     ; in [u.pbase]
  2991 00005728 770E                <1> 	ja	short cpass_1
  2992                              <1> 	; 02/07/2015
  2993 0000572A 833D[F56E0000]00    <1>         cmp     dword [u.ppgdir], 0  ; is the caller os kernel
  2994 00005731 7427                <1>         je      short cpass_k       ; (sysexec, '/etc/init') ? 
  2995                              <1> 	; 08/06/2015 - 10/07/2015
  2996 00005733 E8C7FDFFFF          <1> 	call	trans_addr_r
  2997                              <1> cpass_1:
  2998                              <1> 	; 02/07/2015
  2999                              <1> 	; 24/06/2015
  3000 00005738 66FF0D[FD6E0000]    <1> 	dec	word [u.pcount]
  3001                              <1> cpass_2: 
  3002                              <1> 	; 10/10/2015
  3003                              <1> 	; 02/07/2015
  3004 0000573F 8B15[F96E0000]      <1> 	mov	edx, [u.pbase]
  3005 00005745 8A02                <1> 	mov	al, [edx] ; 10/10/2015
  3006                              <1> 		; movb *u.base,r1 / take the character pointed to 
  3007                              <1> 				; / by u.base and put it in r1
  3008 00005747 FF05[C06E0000]      <1> 	inc	dword [u.nread]
  3009                              <1> 		; inc u.nread / increment no. of bytes transferred
  3010 0000574D FF05[B86E0000]      <1> 	inc	dword [u.base]
  3011                              <1> 		; inc u.base / increment the buffer address to point to the
  3012                              <1> 			   ; / next byte
  3013 00005753 FF05[F96E0000]      <1> 	inc	dword [u.pbase] ; 04/06/2015
  3014                              <1> cpass_3:
  3015 00005759 C3                  <1> 	retn
  3016                              <1> 		; rts	r0 / next byte
  3017                              <1> 	; 1: 
  3018                              <1> 		; mov (sp)+,r0 
  3019                              <1> 		         ; / put return address of calling routine into r0
  3020                              <1> 		; mov (sp)+,r1 / i-number in r1
  3021                              <1> 		; rts r0 / non-local return
  3022                              <1> cpass_k:
  3023                              <1> 	; 02/07/2015
  3024                              <1> 	; The caller is os kernel 
  3025                              <1> 	; (get sysexec arguments from kernel's memory space)
  3026                              <1> 	;
  3027 0000575A 8B1D[B86E0000]      <1> 	mov	ebx, [u.base]
  3028 00005760 66C705[FD6E0000]00- <1>         mov     word [u.pcount], PAGE_SIZE ; 4096
  3028 00005768 10                  <1>
  3029 00005769 891D[F96E0000]      <1> 	mov	[u.pbase], ebx
  3030 0000576F EBCE                <1> 	jmp	short cpass_2
  3031                              <1> 	
  3032                              <1> sioreg: 
  3033                              <1> 	; 25/07/2015
  3034                              <1> 	; 18/07/2015
  3035                              <1> 	; 02/07/2015
  3036                              <1> 	; 17/06/2015
  3037                              <1> 	; 09/06/2015
  3038                              <1> 	; 19/05/2015 (Retro UNIX 386 v1 - Beginning)
  3039                              <1> 	; 12/03/2013 - 22/07/2013 (Retro UNIX 8086 v1)
  3040                              <1> 	;
  3041                              <1> 	; INPUTS -> 
  3042                              <1> 	;     eBX = system buffer (data) address (r5)
  3043                              <1> 	;     [u.fofp] = pointer to file offset pointer
  3044                              <1> 	;     [u.base] = virtual address of the user buffer
  3045                              <1> 	;     [u.pbase] = physical address of the user buffer
  3046                              <1> 	;     [u.count] = byte count
  3047                              <1> 	;     [u.pcount] = byte count within page frame 			
  3048                              <1> 	; OUTPUTS -> 
  3049                              <1> 	;     eSI = user data offset (r1)
  3050                              <1> 	;     eDI = system (I/O) buffer offset (r2)
  3051                              <1> 	;     eCX = byte count (r3)
  3052                              <1> 	;     EAX = remain bytes after byte count within page frame
  3053                              <1> 	;	(If EAX > 0, transfer will continue from the next page)
  3054                              <1>         ;
  3055                              <1> 	; ((Modified registers:  EDX))
  3056                              <1>  
  3057 00005771 8B35[A86E0000]      <1>         mov     esi, [u.fofp]
  3058 00005777 8B3E                <1>         mov     edi, [esi]
  3059                              <1> 		; mov *u.fofp,r2 / file offset (in bytes) is moved to r2
  3060 00005779 89F9                <1> 	mov	ecx, edi
  3061                              <1> 		; mov r2,r3 / and also to r3
  3062 0000577B 81C900FEFFFF        <1> 	or	ecx, 0FFFFFE00h
  3063                              <1> 		; bis $177000,r3 / set bits 9,...,15 of file offset in r3
  3064 00005781 81E7FF010000        <1> 	and	edi, 1FFh
  3065                              <1> 		; bic $!777,r2 / calculate file offset mod 512.
  3066 00005787 01DF                <1> 	add	edi, ebx ; EBX = system buffer (data) address
  3067                              <1> 		; add r5,r2 / r2 now points to 1st byte in system buffer
  3068                              <1> 			  ; / where data is to be placed
  3069                              <1>                 ; mov u.base,r1 / address of data is in r1
  3070 00005789 F7D9                <1> 	neg	ecx
  3071                              <1> 		; neg r3 / 512 - file offset (mod512.) in r3 
  3072                              <1> 		       ; / (i.e., the no. of free bytes in the file block)
  3073 0000578B 3B0D[BC6E0000]      <1> 	cmp	ecx, [u.count]
  3074                              <1> 		; cmp r3,u.count / compare this with the no. of data bytes
  3075                              <1> 			       ; / to be written to the file
  3076 00005791 7606                <1> 	jna	short sioreg_0
  3077                              <1> 		; blos	2f / if less than branch. Use the no. of free bytes
  3078                              <1> 			 ; / in the file block as the number to be written
  3079 00005793 8B0D[BC6E0000]      <1> 	mov	ecx, [u.count]
  3080                              <1> 		; mov u.count,r3 / if greater than, use the no. of data 
  3081                              <1> 			       ; / bytes as the number to be written
  3082                              <1> sioreg_0:
  3083                              <1> 	; 17/06/2015
  3084 00005799 803D[FF6E0000]00    <1> 	cmp	byte [u.kcall], 0 
  3085 000057A0 7613                <1> 	jna	short sioreg_1
  3086                              <1> 	; 25/07/2015
  3087                              <1> 	; the caller is 'mkdir' or 'namei'
  3088 000057A2 A1[B86E0000]        <1> 	mov	eax, [u.base] ; 25/07/2015
  3089 000057A7 A3[F96E0000]        <1> 	mov 	[u.pbase], eax ; physical address = virtual address
  3090 000057AC 66890D[FD6E0000]    <1> 	mov	word [u.pcount], cx ; remain bytes in buffer (1 sector)
  3091 000057B3 EB0B                <1> 	jmp	short sioreg_2
  3092                              <1> sioreg_1:
  3093                              <1> 	; 25/07/2015
  3094                              <1> 	; 18/07/2015
  3095                              <1> 	; 09/06/2015 
  3096 000057B5 0FB715[FD6E0000]    <1> 	movzx	edx, word [u.pcount]
  3097                              <1> 		; ecx and [u.pcount] are always > 0, here
  3098 000057BC 39D1                <1> 	cmp	ecx, edx	
  3099 000057BE 772A                <1> 	ja	short sioreg_4 ; transfer count > [u.pcount]
  3100                              <1> sioreg_2: ; 2:
  3101 000057C0 31C0                <1> 	xor 	eax, eax ; 25/07/2015
  3102                              <1> sioreg_3:
  3103 000057C2 010D[C06E0000]      <1> 	add 	[u.nread], ecx
  3104                              <1> 		; add r3,u.nread / r3 + number of bytes xmitted 
  3105                              <1> 			         ; / during write is put into u.nread
  3106 000057C8 290D[BC6E0000]      <1> 	sub 	[u.count], ecx
  3107                              <1> 		; sub r3,u.count / u.count = no. of bytes that still 
  3108                              <1> 			       ; / must be written or read
  3109 000057CE 010D[B86E0000]      <1> 	add 	[u.base], ecx
  3110                              <1> 		; add r3,u.base / u.base points to the 1st of the remaining
  3111                              <1> 			      ; / data bytes
  3112 000057D4 010E                <1>         add 	[esi], ecx 
  3113                              <1> 		; add r3,*u.fofp / new file offset = number of bytes done
  3114                              <1> 			       ; / + old file offset
  3115                              <1> 	; 25/07/2015
  3116 000057D6 8B35[F96E0000]      <1> 	mov	esi, [u.pbase]
  3117 000057DC 66290D[FD6E0000]    <1> 	sub	[u.pcount], cx
  3118 000057E3 010D[F96E0000]      <1> 	add	[u.pbase], ecx
  3119 000057E9 C3                  <1>         retn
  3120                              <1> 		; rts r0
  3121                              <1> 		; transfer count > [u.pcount]
  3122                              <1> sioreg_4:
  3123                              <1> 	; 25/07/2015
  3124                              <1> 	; transfer count > [u.pcount] 
  3125                              <1> 	; (ecx > edx)
  3126 000057EA 89C8                <1> 	mov	eax, ecx
  3127 000057EC 29D0                <1> 	sub	eax, edx ; remain bytes for 1 sector (block) transfer 
  3128 000057EE 89D1                <1> 	mov	ecx, edx ; current transfer count = [u.pcount]
  3129 000057F0 EBD0                <1> 	jmp	short sioreg_3
  2102                                  %include 'u7.s'        ; 18/04/2015
  2103                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS7.INC
  2104                              <1> ; Last Modification: 03/03/2022
  2105                              <1> ; ----------------------------------------------------------------------------
  2106                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2107                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2108                              <1> ;
  2109                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2110                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2111                              <1> ; <Bell Laboratories (17/3/1972)>
  2112                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2113                              <1> ;
  2114                              <1> ; Retro UNIX 8086 v1 - U7.ASM (13/07/2014) //// UNIX v1 -> u7.s
  2115                              <1> ;
  2116                              <1> ; ****************************************************************************
  2117                              <1> 
  2118                              <1> sysmount: ; / mount file system; args special; name
  2119                              <1> 	; 09/02/2022
  2120                              <1> 	; 08/02/2022
  2121                              <1> 	; 07/02/2022
  2122                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2123                              <1> 	; 14/11/2015
  2124                              <1> 	; 24/10/2015
  2125                              <1> 	; 13/10/2015
  2126                              <1> 	; 10/07/2015
  2127                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2128                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2129                              <1> 	;
  2130                              <1> 	; 'sysmount' anounces to the system that a removable 
  2131                              <1> 	; file system has been mounted on a special file.
  2132                              <1> 	; The device number of the special file is obtained via
  2133                              <1> 	; a call to 'getspl'. It is put in the I/O queue entry for
  2134                              <1> 	; dismountable file system (sb1) and the I/O queue entry is
  2135                              <1> 	; set up to read (bit 10 is set). 'ppoke' is then called to
  2136                              <1> 	; to read file system into core, i.e. the first block on the
  2137                              <1> 	; mountable file system is read in. This block is super block
  2138                              <1> 	; for the file system. This call is super user restricted.	
  2139                              <1> 	;
  2140                              <1> 	; Calling sequence:
  2141                              <1> 	;	sysmount; special; name
  2142                              <1> 	; Arguments:
  2143                              <1> 	;	special - pointer to name of special file (device)
  2144                              <1> 	;	name -  pointer to name of the root directory of the
  2145                              <1> 	;		newly mounted file system. 'name' should 
  2146                              <1> 	;		always be a directory.
  2147                              <1> 	; Inputs: - 
  2148                              <1> 	; Outputs: -
  2149                              <1> 	; ...............................................................
  2150                              <1> 	;				
  2151                              <1> 	; Retro UNIX 8086 v1 modification: 
  2152                              <1> 	;       'sysmount' system call has two arguments; so,
  2153                              <1> 	;	* 1st argument, special is pointed to by BX register
  2154                              <1> 	;	* 2nd argument, name is in CX register
  2155                              <1> 	;
  2156                              <1> 	;	NOTE: Device numbers, names and related procedures are 
  2157                              <1> 	;	       already modified for IBM PC compatibility and 
  2158                              <1> 	;	       Retro UNIX 8086 v1 device configuration.	
  2159                              <1> 	
  2160                              <1> 	;call	arg2
  2161                              <1> 		; jsr r0,arg2 / get arguments special and name
  2162 000057F2 891D[B06E0000]      <1> 	mov	[u.namep], ebx
  2163                              <1> 	; 09/02/2022
  2164                              <1> 	;push	ecx ; directory name
  2165 000057F8 66833D[846E0000]00  <1> 	cmp	word [mnti], 0
  2166                              <1> 		; tst mnti / is the i-number of the cross device file
  2167                              <1> 			 ; / zero?
  2168                              <1> 	;;ja	error
  2169                              <1>         	; bne errora / no, error
  2170                              <1> 	;ja	sysmnt_err0
  2171                              <1> 	; 11/01/2022
  2172 00005800 7605                <1> 	jna	short sysmnt_0
  2173 00005802 E907010000          <1> 	jmp	sysmnt_err0
  2174                              <1> sysmnt_0:
  2175                              <1> 	; 09/02/2022
  2176 00005807 51                  <1> 	push	ecx ; directory name
  2177 00005808 E8E9000000          <1> 	call	getspl
  2178                              <1> 		; jsr r0,getspl / get special files device number in r1
  2179                              <1> 	; 09/02/2022
  2180 0000580D 8F05[B06E0000]      <1> 	pop	dword [u.namep] ; directory name
  2181                              <1> 	; 13/10/2015
  2182                              <1> 	;movzx	ebx, ax ; Retro UNIX 8086 v1 device number (0 to 5)
  2183                              <1> 	; 11/01/2022
  2184 00005813 29DB                <1> 	sub	ebx, ebx
  2185 00005815 88C3                <1> 	mov	bl, al
  2186 00005817 F683[1A660000]80    <1> 	test    byte [ebx+drv.status], 80h ; 24/10/2015 
  2187 0000581E 750F                <1> 	jnz	short sysmnt_1
  2188                              <1> sysmnt_err1:
  2189 00005820 C705[ED6E0000]0F00- <1>         mov     dword [u.error], ERR_DRV_NOT_RDY ; drive not ready !
  2189 00005828 0000                <1>
  2190 0000582A E9A3E2FFFF          <1> 	jmp	error
  2191                              <1> sysmnt_1:
  2192                              <1> 	; 09/02/2022
  2193                              <1> 	;pop	dword [u.namep]
  2194                              <1>         	; mov (sp)+,u.namep / put the name of file to be placed
  2195                              <1> 				  ; / on the device
  2196                              <1> 	; 14/11/2015
  2197 0000582F 53                  <1> 	push	ebx ; 13/10/2015
  2198                              <1> 		; mov r1,-(sp) / save the device number
  2199                              <1>         ;
  2200 00005830 E89BF1FFFF          <1> 	call	namei
  2201                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2202                              <1> 		       ; ax = 0 -> file not found 	
  2203                              <1> 	;jz	error
  2204                              <1> 	;jc	error
  2205                              <1> 		; jsr r0,namei / get the i-number of the file
  2206                              <1>                	; br errora
  2207 00005835 730F                <1> 	jnc	short sysmnt_2
  2208                              <1> sysmnt_err2:
  2209 00005837 C705[ED6E0000]0C00- <1>         mov     dword [u.error], ERR_FILE_NOT_FOUND ; drive not ready !
  2209 0000583F 0000                <1>
  2210 00005841 E98CE2FFFF          <1> 	jmp	error
  2211                              <1> sysmnt_2:	
  2212 00005846 66A3[846E0000]      <1> 	mov	[mnti], ax
  2213                              <1>         	; mov r1,mnti / put it in mnti
  2214                              <1> 	; 11/01/2022
  2215 0000584C BB[587D0000]        <1> 	mov	ebx, sb1 ; super block buffer header (of mounted disk)
  2216                              <1> sysmnt_3: ;1:
  2217                              <1>         ;cmp	byte [ebx+1], 0
  2218                              <1> 		; tstb sb1+1 / is 15th bit of I/O queue entry for
  2219                              <1> 			   ; / dismountable device set?
  2220                              <1>         ;jna	short sysmnt_4		
  2221                              <1> 		; bne 1b / (inhibit bit) yes, skip writing
  2222                              <1> 	;call	idle 	; (wait for hardware interrupt)
  2223                              <1> 	;jmp	short sysmnt_3
  2224                              <1> sysmnt_4:   
  2225 00005851 58                  <1> 	pop	eax ; Retro UNIX 8086 v1 device number/ID (0 to 5)     
  2226 00005852 A2[816E0000]        <1> 	mov	[mdev], al
  2227                              <1> 		; mov (sp),mntd / no, put the device number in mntd
  2228 00005857 8803                <1> 	mov	[ebx], al
  2229                              <1>         	; movb (sp),sb1 / put the device number in the lower byte
  2230                              <1> 			      ; / of the I/O queue entry
  2231                              <1> 	;mov	byte [cdev], 1 ; mounted device/drive
  2232                              <1>         	; mov (sp)+,cdev / put device number in cdev
  2233 00005859 66810B0004          <1>         or	word [ebx], 400h ; Bit 10, 'read' flag/bit
  2234                              <1> 		; bis $2000,sb1 / set the read bit
  2235                              <1> 	; Retro UNIX 386 v1 modification : 
  2236                              <1> 	;	32 bit block number at buffer header offset 4
  2237 0000585E C7430401000000      <1> 	mov	dword [ebx+4], 1 ; physical block number = 1
  2238 00005865 E8E5050000          <1> 	call 	diskio
  2239 0000586A 7345                <1> 	jnc	short sysmnt_5
  2240 0000586C 31C0                <1> 	xor 	eax, eax
  2241 0000586E 66A3[846E0000]      <1> 	mov	[mnti], ax ; 0
  2242 00005874 A2[816E0000]        <1> 	mov	[mdev], al ; 0
  2243                              <1> 	;mov	[cdev], al ; 0
  2244                              <1> 	; 08/02/2022
  2245 00005879 803D[006F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2246 00005880 7508                <1> 	jne	short sysmnt_err3
  2247                              <1> 	; yes, clear [u.brwdev] for next check
  2248                              <1> 	; ([u.error] = DRV_NOT_RDY or OUT_OF_VOLUME error) 
  2249 00005882 FE05[006F0000]      <1> 	inc	byte [u.brwdev] ; 0, reset
  2250 00005888 EB0A                <1> 	jmp	short sysmnt_err4
  2251                              <1> sysmnt_err3:	; 08/02/2022
  2252                              <1> 	; no, set [u.error] to disk read error
  2253 0000588A C705[ED6E0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; 'disk read error !'
  2253 00005892 0000                <1>
  2254                              <1> sysmnt_err4:
  2255                              <1> 	; 08/02/2022
  2256                              <1> 	; 14/11/2015
  2257 00005894 FEC8                <1> 	dec 	al
  2258 00005896 8903                <1> 	mov	[ebx], eax ; 000000FFh
  2259 00005898 FEC0                <1> 	inc	al
  2260 0000589A 48                  <1> 	dec	eax
  2261 0000589B 894304              <1> 	mov	[ebx+4], eax ; 0FFFFFFFFh
  2262 0000589E E92FE2FFFF          <1> 	jmp	error
  2263                              <1> sysmnt_invd:
  2264                              <1> 	; 08/02/2022
  2265 000058A3 C705[ED6E0000]1C00- <1> 	mov	 dword [u.error], ERR_INV_FS ; 28
  2265 000058AB 0000                <1>
  2266                              <1> 				 ;'invalid fs/superblock !' error
  2267 000058AD 30C0                <1> 	xor	al, al
  2268 000058AF EBE3                <1> 	jmp	short sysmnt_err4	
  2269                              <1> 
  2270                              <1> sysmnt_5:
  2271                              <1> 	; 08/02/2022
  2272                              <1> 	; 11/01/2022 (BugFix)
  2273                              <1> 	; 14/11/2015 (Retro UNIX 386 v1 modification)
  2274                              <1> 	; (Following check is needed to prevent mounting an
  2275                              <1> 	; invalid file system (invalid super block).
  2276                              <1> 	; 
  2277 000058B1 0FB603              <1> 	movzx	eax, byte [ebx] ; device number
  2278 000058B4 C0E002              <1> 	shl	al, 2 ; 4*index
  2279 000058B7 8B88[FE650000]      <1> 	mov	ecx, [eax+drv.size] ; volume (fs) size
  2280 000058BD C1E903              <1> 	shr 	ecx, 3 ; 11/01/2021 (8 sectors per 1 fbm byte)
  2281                              <1> 	; ecx = number of free map bytes (required)
  2282                              <1> 	;movzx	edx, word [sb1+8] ; the 1st data word ('mount:')
  2283 000058C0 0FB75308            <1> 	movzx	edx, word [ebx+8] ; the 1st data word (of the buffer)	
  2284                              <1> 	; edx = number of free blocks map bytes
  2285                              <1> 	;shl	edx, 3 ; convert free map bytes to free map bits
  2286                              <1> 	; 07/02/2022
  2287                              <1> 	;xor	al, al ; 08/02/2022
  2288 000058C4 39D1                <1> 	cmp	ecx, edx ; compare free map bits and volume size
  2289                              <1> 			 ; (in sectors), if they are not equal
  2290                              <1> 			 ; the disk to be mounted is an...	
  2291 000058C6 75DB                <1> 	jne	short sysmnt_invd ; invalid disk !
  2292                              <1> 			 ; (which has not got a valid super block)
  2293                              <1> 	;
  2294 000058C8 C6430100            <1> 	mov	byte [ebx+1], 0
  2295                              <1> 	       	; jsr r0,ppoke / read in entire file system
  2296                              <1> ;sysmnt_6: ;1:
  2297                              <1> 	;;cmp	byte [sb1+1], 0
  2298                              <1> 		; tstb sb1+1 / done reading?
  2299                              <1>    	;;jna	sysret
  2300                              <1> 	;;call	idle ; (wait for hardware interrupt)
  2301                              <1> 	;;jmp	short sysmnt_6
  2302                              <1> 		; bne 1b / no, wait
  2303                              <1>         	; br sysreta / yes
  2304 000058CC E921E2FFFF          <1> 	jmp	sysret
  2305                              <1> 
  2306                              <1> sysumount: ; / special dismount file system
  2307                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2308                              <1> 	; 16/05/2015 (Retro UNIX 386 v1 - Beginning)
  2309                              <1> 	; 09/07/2013 - 04/11/2013 (Retro UNIX 8086 v1)
  2310                              <1> 	;
  2311                              <1> 	; 04/11/2013
  2312                              <1> 	; 09/07/2013
  2313                              <1> 	; 'sysumount' anounces to the system that the special file, 
  2314                              <1> 	; indicated as an argument is no longer contain a removable
  2315                              <1> 	; file system. 'getspl' gets the device number of the special
  2316                              <1> 	; file. If no file system was mounted on that device an error
  2317                              <1> 	; occurs. 'mntd' and 'mnti' are cleared and control is passed
  2318                              <1> 	; to 'sysret'.
  2319                              <1> 	;
  2320                              <1> 	; Calling sequence:
  2321                              <1> 	;	sysmount; special
  2322                              <1> 	; Arguments:
  2323                              <1> 	;	special - special file to dismount (device)
  2324                              <1> 	;
  2325                              <1> 	; Inputs: - 
  2326                              <1> 	; Outputs: -
  2327                              <1> 	; ...............................................................
  2328                              <1> 	;				
  2329                              <1> 	; Retro UNIX 8086 v1 modification: 
  2330                              <1> 	;       'sysumount' system call has one argument; so,
  2331                              <1> 	;	* Single argument, special is pointed to by BX register
  2332                              <1> 	;
  2333                              <1> 	
  2334                              <1> 	;mov 	ax, 1 ; one/single argument, put argument in BX	
  2335                              <1> 	;call	arg
  2336                              <1> 		; jsr r0,arg; u.namep / point u.namep to special
  2337 000058D1 891D[B06E0000]      <1>         mov	[u.namep], ebx
  2338 000058D7 E81A000000          <1> 	call	getspl
  2339                              <1> 		; jsr r0,getspl / get the device number in r1
  2340 000058DC 3A05[816E0000]      <1> 	cmp	al, [mdev]
  2341                              <1> 		; cmp r1,mntd / is it equal to the last device mounted?
  2342 000058E2 752A                <1> 	jne	short sysmnt_err0 ; 'permission denied !' error
  2343                              <1> 	;jne	error
  2344                              <1>         	; bne errora / no error
  2345 000058E4 30C0                <1> 	xor	al, al ; ah = 0
  2346                              <1> sysumnt_0: ;1:
  2347                              <1>      	; 11/01/2022
  2348                              <1> 	;cmp 	[sb1+1], al ; 0
  2349                              <1> 	;	; tstb sb1+1 / yes, is the device still doing I/O 
  2350                              <1> 	;		   ; / (inhibit bit set)?
  2351                              <1> 	;jna	short sysumnt_1		
  2352                              <1> 	;	; bne 1b / yes, wait
  2353                              <1> 	;call	idle ; (wait for hardware interrupt)
  2354                              <1> 	;jmp	short sysumnt_0
  2355                              <1> sysumnt_1:        
  2356 000058E6 A2[816E0000]        <1> 	mov	[mdev], al ; 0
  2357                              <1> 	     	; clr mntd / no, clear these
  2358 000058EB 66A3[846E0000]      <1>    	mov	[mnti], ax ; 0
  2359                              <1>         	; clr mnti
  2360 000058F1 E9FCE1FFFF          <1>         jmp	sysret
  2361                              <1> 		; br sysreta / return
  2362                              <1> 
  2363                              <1> getspl: ; / get device number from a special file name
  2364 000058F6 E8D5F0FFFF          <1> 	call	namei
  2365                              <1> 	;or	ax, ax ; Retro UNIX 8086 v1 modification !
  2366                              <1> 		       ; ax = 0 -> file not found 	
  2367                              <1> 	;jc	sysmnt_err2 ; 'file not found !' error
  2368                              <1> 	; 11/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2369 000058FB 7305                <1> 	jnc	short getspl_0
  2370 000058FD E935FFFFFF          <1> 	jmp	sysmnt_err2 ; 'file not found !' error
  2371                              <1> getspl_0:
  2372                              <1> 	;jz	error
  2373                              <1> 	;jc	error
  2374                              <1> 		; jsr r0,namei / get the i-number of the special file
  2375                              <1>                 ; br errora / no such file
  2376 00005902 6683E803            <1>         sub	ax, 3 ; Retro UNIX 8086 v1 modification !
  2377                              <1> 		      ;	i-number-3, 0 = fd0, 5 = hd3 
  2378                              <1> 		; sub $4,r1 / i-number-4 rk=1,tap=2+n
  2379 00005906 7206                <1>         jc	short sysmnt_err0 ; 'permission denied !' error
  2380                              <1> 	;jc	error
  2381                              <1> 		; ble errora / less than 0?  yes, error
  2382 00005908 6683F805            <1>         cmp	ax, 5 ;
  2383                              <1> 		; cmp r1,$9. / greater than 9  tap 7
  2384                              <1> 	;ja	short sysmnt_err0 ; 'permission denied !' error
  2385                              <1> 	;;ja	error
  2386                              <1> 		; bgt errora / yes, error
  2387                              <1> 	; 11/01/2022
  2388 0000590C 760F                <1> 	jna	short getspl_retn
  2389                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2390                              <1> ;iopen_retn:
  2391                              <1> ;	retn
  2392                              <1> 		; rts r0 / return with device number in r1
  2393                              <1> sysmnt_err0:
  2394 0000590E C705[ED6E0000]0B00- <1> 	mov	dword [u.error], ERR_FILE_ACCESS ; permission denied !
  2394 00005916 0000                <1>
  2395 00005918 E9B5E1FFFF          <1> 	jmp	error
  2396                              <1> 
  2397                              <1> getspl_retn:
  2398                              <1> 	; AX = Retro UNIX 8086 v1 Device Number (0 to 5)
  2399                              <1> 	; 11/01/2022
  2400                              <1> iopen_retn:
  2401 0000591D C3                  <1> 	retn
  2402                              <1> 
  2403                              <1> iopen:
  2404                              <1> 	; 11/01/2022
  2405                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2406                              <1> 	; 19/05/2015
  2407                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2408                              <1> 	; 21/05/2013 - 27/08/2013 (Retro UNIX 8086 v1)
  2409                              <1> 	;
  2410                              <1> 	; open file whose i-number is in r1
  2411                              <1> 	; 
  2412                              <1> 	; INPUTS ->
  2413                              <1> 	;    r1 - inode number
  2414                              <1> 	; OUTPUTS ->
  2415                              <1> 	;    file's inode in core	
  2416                              <1> 	;    r1 - inode number (positive)
  2417                              <1> 	;
  2418                              <1> 	; ((AX = R1))
  2419                              <1>         ; ((Modified registers: edx, ebx, ecx, esi, edi, ebp)) 
  2420                              <1> 	;        
  2421                              <1> ; / open file whose i-number is in r1
  2422 0000591E F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2423                              <1> 		; tst r1 / write or read access?
  2424 00005921 7568                <1>         jnz	short iopen_2
  2425                              <1> 		; blt 2f / write, go to 2f
  2426 00005923 B202                <1> 	mov	dl, 2 ; read access
  2427 00005925 E844F9FFFF          <1> 	call	access
  2428                              <1>         	; jsr r0,access; 2 
  2429                              <1> 	; / get inode into core with read access
  2430                              <1> 	; DL=2
  2431                              <1> iopen_0:
  2432 0000592A 6683F828            <1>         cmp	ax, 40
  2433                              <1> 		; cmp r1,$40. / is it a special file
  2434 0000592E 77ED                <1>         ja	short iopen_retn
  2435                              <1> 		; bgt  3f / no. 3f
  2436 00005930 50                  <1> 	push	eax ; 08/01/2022
  2437                              <1> 	;push	ax
  2438                              <1> 		; mov r1,-(sp) / yes, figure out
  2439 00005931 0FB6D8              <1> 	movzx	ebx, al
  2440 00005934 C0E302              <1> 	shl	bl, 2 ; * 4 ; 08/01/2022
  2441                              <1> 	;shl	bx, 2
  2442                              <1> 		; asl r1
  2443 00005937 81C3[3B590000]      <1>         add     ebx, iopen_1 - 4
  2444 0000593D FF23                <1> 	jmp	dword [ebx]
  2445                              <1>         	; jmp *1f-2(r1) / which one and transfer to it
  2446                              <1> iopen_1: ; 1:
  2447 0000593F [A3590000]          <1> 	dd	otty ; tty, AX = 1 (runix)
  2448                              <1>  		 ;otty / tty ; r1=2
  2449                              <1>         	 ;oppt / ppt ; r1=4
  2450 00005943 [5B5A0000]          <1> 	dd	sret ; mem, AX = 2 (runix)
  2451                              <1> 		 ;sret / mem ; r1=6
  2452                              <1> 		 ;sret / rf0
  2453                              <1>         	 ;sret / rk0
  2454                              <1>         	 ;sret / tap0
  2455                              <1>         	 ;sret / tap1
  2456                              <1>         	 ;sret / tap2
  2457                              <1>         	 ;sret / tap3
  2458                              <1>         	 ;sret / tap4
  2459                              <1>         	 ;sret / tap5
  2460                              <1>         	 ;sret / tap6
  2461                              <1>         	 ;sret / tap7
  2462 00005947 [5B5A0000]          <1>         dd	sret ; fd0, AX = 3 (runix only)
  2463 0000594B [5B5A0000]          <1>         dd	sret ; fd1, AX = 4 (runix only)
  2464 0000594F [5B5A0000]          <1>         dd	sret ; hd0, AX = 5 (runix only)
  2465 00005953 [5B5A0000]          <1>         dd	sret ; hd1, AX = 6 (runix only) 
  2466 00005957 [5B5A0000]          <1>         dd	sret ; hd2, AX = 7 (runix only)
  2467 0000595B [5B5A0000]          <1>         dd	sret ; hd3, AX = 8 (runix only) 
  2468                              <1> 	;dd	error ; lpr, AX = 9 (error !)
  2469 0000595F [5B5A0000]          <1>         dd      sret ; lpr, AX = 9 (runix)
  2470 00005963 [B4590000]          <1> 	dd	ocvt ; tty0, AX = 10 (runix)	  
  2471                              <1> 		 ;ocvt / tty0
  2472 00005967 [B4590000]          <1> 	dd	ocvt ; tty1, AX = 11 (runix)	  
  2473                              <1> 		 ;ocvt / tty1
  2474 0000596B [B4590000]          <1> 	dd	ocvt ; tty2, AX = 12 (runix)	  
  2475                              <1> 		 ;ocvt / tty2
  2476 0000596F [B4590000]          <1> 	dd	ocvt ; tty3, AX = 13 (runix)	  
  2477                              <1> 		 ;ocvt / tty3
  2478 00005973 [B4590000]          <1> 	dd	ocvt ; tty4, AX = 14 (runix)	  
  2479                              <1> 		 ;ocvt / tty4
  2480 00005977 [B4590000]          <1> 	dd	ocvt ; tty5, AX = 15 (runix)	  
  2481                              <1> 		 ;ocvt / tty5
  2482 0000597B [B4590000]          <1> 	dd	ocvt ; tty6, AX = 16 (runix)	  
  2483                              <1> 		 ;ocvt / tty6
  2484 0000597F [B4590000]          <1> 	dd	ocvt ; tty7, AX = 17 (runix)	  
  2485                              <1> 		 ;ocvt / tty7
  2486 00005983 [B4590000]          <1> 	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2487                              <1> 		 ;error / crd
  2488 00005987 [B4590000]          <1> 	dd	ocvt ; COM2, AX = 19 (runix only)
  2489                              <1> 
  2490                              <1> iopen_2: ; 2: / check open write access
  2491 0000598B 66F7D8              <1> 	neg	ax
  2492                              <1> 		;neg r1 / make inode number positive
  2493 0000598E B201                <1> 	mov	dl, 1 ; write access
  2494 00005990 E8D9F8FFFF          <1> 	call	access
  2495                              <1> 		;jsr r0,access; 1 / get inode in core
  2496                              <1> 	; DL=1
  2497                              <1> 	; 11/01/2022
  2498 00005995 F605[996B0000]40    <1> 	test	byte [i.flgs+1], 40h
  2499                              <1> 	;test	word [i.flgs], 4000h ; Bit 14 : Directory flag
  2500                              <1>  		; bit $40000,i.flgs / is it a directory?
  2501 0000599C 748C                <1> 	jz	short iopen_0
  2502                              <1> 	;mov	[u.error], ERR_DIR_ACCESS
  2503                              <1> 	;jmp	error ; permission denied !
  2504 0000599E E96BFFFFFF          <1> 	jmp	sysmnt_err0
  2505                              <1> 	;;jnz	error		
  2506                              <1>        		; bne 2f / yes, transfer (error)
  2507                              <1>         ;;jmp	short iopen_0
  2508                              <1> 	;cmp	ax, 40
  2509                              <1> 		; cmp r1,$40. / no, is it a special file?
  2510                              <1>         ;ja	short iopen_2
  2511                              <1> 		; bgt 3f / no, return
  2512                              <1> 	;push	ax
  2513                              <1> 		; mov r1,-(sp) / yes
  2514                              <1> 	;movzx	ebx, al
  2515                              <1> 	;shl	bx, 1
  2516                              <1> 		; asl r1
  2517                              <1> 	;add	ebx, ipen_3 - 2
  2518                              <1> 	;jmp	dword [ebx]
  2519                              <1> 		; jmp *1f-2(r1) / figure out 
  2520                              <1> 			; / which special file it is and transfer
  2521                              <1> ;iopen_3: ; 1:
  2522                              <1> ;	dd 	otty ; tty, AX = 1 (runix)
  2523                              <1>  		 ;otty / tty ; r1=2
  2524                              <1>         	 ;leadr / ppt ; r1=4
  2525                              <1> ;	dd	sret ; mem, AX = 2 (runix)
  2526                              <1> 		 ;sret / mem ; r1=6
  2527                              <1> 		 ;sret / rf0
  2528                              <1>         	 ;sret / rk0
  2529                              <1>         	 ;sret / tap0
  2530                              <1>         	 ;sret / tap1
  2531                              <1>         	 ;sret / tap2
  2532                              <1>         	 ;sret / tap3
  2533                              <1>         	 ;sret / tap4
  2534                              <1>         	 ;sret / tap5
  2535                              <1>         	 ;sret / tap6
  2536                              <1>         	 ;sret / tap7
  2537                              <1> ;	dd 	sret ; fd0, AX = 3 (runix only)
  2538                              <1> ;	dd 	sret ; fd1, AX = 4 (runix only)
  2539                              <1> ;	dd 	sret ; hd0, AX = 5 (runix only)
  2540                              <1> ;	dd 	sret ; hd1, AX = 6 (runix only)	
  2541                              <1> ;	dd 	sret ; hd2, AX = 7 (runix only)
  2542                              <1> ;	dd 	sret ; hd3, AX = 8 (runix only)	
  2543                              <1> ;	dd	sret ; lpr, AX = 9  (runix)
  2544                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2545                              <1> ;	dd	sret ; tty0, AX = 10 (runix)	  
  2546                              <1> 		 ;ocvt / tty0
  2547                              <1> ;	dd	sret ; tty1, AX = 11 (runix)	  
  2548                              <1> 		 ;ocvt / tty1
  2549                              <1> ;	dd	sret ; tty2, AX = 12 (runix)	  
  2550                              <1> 		 ;ocvt / tty2
  2551                              <1> ;	dd	sret ; tty3, AX = 13 (runix)	  
  2552                              <1> 		 ;ocvt / tty3
  2553                              <1> ;	dd	sret ; tty4, AX = 14 (runix)	  
  2554                              <1> 		 ;ocvt / tty4
  2555                              <1> ;	dd	sret ; tty5, AX = 15 (runix)	  
  2556                              <1> 		 ;ocvt / tty5
  2557                              <1> ;	dd	sret ; tty6, AX = 16 (runix)	  
  2558                              <1> 		 ;ocvt / tty6
  2559                              <1> ;	dd	sret ; tty7, AX = 17 (runix)	  
  2560                              <1> 		 ;ocvt / tty7
  2561                              <1> ;	dd	ocvt ; COM1, AX = 18 (runix only)	  
  2562                              <1> 		 ;/ ejec / lpr
  2563                              <1> ;	dd	ocvt ; COM2, AX = 19 (runix only)
  2564                              <1> 
  2565                              <1> otty: ;/ open console tty for reading or writing
  2566                              <1> 	; 03/03/2022
  2567                              <1> 	; 02/03/2022
  2568                              <1> 	; 26/02/2022
  2569                              <1> 	; 09/02/2022
  2570                              <1> 	; 06/02/2022
  2571                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2572                              <1> 	; 16/11/2015
  2573                              <1> 	; 12/11/2015
  2574                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2575                              <1> 	; 21/05/2013 - 13/07/2014 (Retro UNIX 8086 v1)
  2576                              <1> 	; 16/07/2013
  2577                              <1> 	; Retro UNIX 8086 v1 modification:
  2578                              <1> 	;  If a tty is open for read or write by
  2579                              <1> 	;     a process (u.uno), only same process can open
  2580                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2581                              <1> 	;
  2582                              <1> 	; (INPUT: DL=2 for Read, DL=1 for Write, DL=0 for sysstty)
  2583                              <1> 	;
  2584 000059A3 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2585 000059AA 8A83[F76B0000]      <1> 	mov	al, [ebx+p.ttyc-1] ; current/console tty
  2586                              <1> 	; 13/01/2014
  2587                              <1> 	;jmp	short ottyp
  2588                              <1> 	; 26/02/2022
  2589 000059B0 88C4                <1> 	mov	ah, al
  2590 000059B2 EB06                <1> 	jmp	short ottypc ; ah = al = console tty number
  2591                              <1> ocvt:
  2592 000059B4 2C0A                <1> 	sub	al, 10
  2593                              <1> ;ottyp:	; (call from sysstty)
  2594                              <1> 	; 08/01/2022
  2595 000059B6 31DB                <1> 	xor	ebx, ebx
  2596                              <1> ottyp:	; (ebx < 256) ; 06/02/2022
  2597                              <1> 	; 26/02/2022
  2598 000059B8 B4FF                <1> 	mov	ah, 0FFh
  2599                              <1> ottypc:
  2600                              <1> 	; 03/03/2022
  2601                              <1> 	; 26/02/2022
  2602                              <1> 	; 09/02/2022
  2603                              <1> 	; 08/01/2022
  2604                              <1> 	; 16/11/2015
  2605                              <1> 	; 12/11/2015
  2606                              <1> 	; 18/05/2015 (32 bit modifications)
  2607                              <1> 	; 06/12/2013 - 13/07/2014
  2608 000059BA 88C6                <1> 	mov	dh, al ; tty number
  2609                              <1> 	;movzx 	ebx, al ; AL = tty number (0 to 9), AH = 0
  2610                              <1> 	; 08/01/2022
  2611 000059BC 88C3                <1> 	mov	bl, al
  2612 000059BE D0E3                <1> 	shl 	bl, 1  ; aligned to word
  2613                              <1> 	; 26/01/2014	
  2614 000059C0 81C3[246B0000]      <1> 	add 	ebx, ttyl
  2615 000059C6 668B0B              <1> 	mov 	cx, [ebx]
  2616                              <1> 		   ; CL = lock value (0 or process number)
  2617                              <1> 		   ; CH = open count 
  2618 000059C9 20C9                <1> 	and 	cl, cl
  2619                              <1> 	; 13/01/2014
  2620                              <1> 	;jz 	short otty_ret
  2621                              <1> 	; 08/01/2022
  2622 000059CB 7447                <1> 	jz 	short ottys_0
  2623                              <1> 	;
  2624                              <1> 	; 16/11/2015
  2625 000059CD 3A0D[E76E0000]      <1> 	cmp 	cl, [u.uno]
  2626 000059D3 746E                <1> 	je	short ottys_3
  2627                              <1> 	;
  2628                              <1> 	;
  2629                              <1> 	; 26/02/2022
  2630                              <1> 	; (is it the console tty of the current process?)
  2631                              <1> 	; ((fast check/permit for console tty open function))
  2632 000059D5 38E0                <1> 	cmp	al, ah ; cmp dh, ah
  2633 000059D7 746A                <1> 	je	short ottys_3 ; bypass parent process check
  2634                              <1> 	;
  2635                              <1> 	; 26/02/2022
  2636                              <1> 	;movzx 	ebx, cl ; the process which has locked the tty
  2637                              <1> 	;shl 	bl, 1
  2638                              <1> 	;mov 	ax, [ebx+p.pid-2]
  2639                              <1> 	;;movzx ebx, byte [u.uno]
  2640                              <1> 	;mov	bl, [u.uno]
  2641                              <1> 	;shl 	bl, 1
  2642                              <1> 	;cmp 	ax, [ebx+p.ppid-2]
  2643                              <1> 	;je 	short ottys_3  ; 16/11/2015
  2644                              <1> 	; 26/02/2022 (BugFix) ; *
  2645 000059D9 0FB6F1              <1> 	movzx 	esi, cl ; the process which has locked the tty
  2646 000059DC D1E6                <1> 	shl 	esi, 1
  2647 000059DE 668B86[B66B0000]    <1> 	mov 	ax, [esi+p.pid-2]
  2648 000059E5 96                  <1> 	xchg	esi, eax
  2649 000059E6 A0[E76E0000]        <1> 	mov	al, [u.uno]
  2650 000059EB D0E0                <1> 	shl 	al, 1
  2651 000059ED 663BB0[D66B0000]    <1> 	cmp 	si, [eax+p.ppid-2]
  2652 000059F4 744D                <1> 	je 	short ottys_3 ; *
  2653                              <1> 	; 26/02/2022
  2654                              <1> 	; check console tty of the process
  2655                              <1> 	; (open permission must be given if the -requested- tty is
  2656                              <1> 	;  console tty of current process)
  2657 000059F6 D0E8                <1> 	shr	al, 1
  2658 000059F8 38B0[F76B0000]      <1> 	cmp	[eax+p.ttyc-1], dh ; console tty ?
  2659 000059FE 7443                <1> 	je 	short ottys_3
  2660                              <1> 	;
  2661                              <1> 	; the tty is locked by another process
  2662                              <1> 	; except the parent process (p.ppid)
  2663                              <1>         ;
  2664                              <1> 	; 09/02/2022
  2665                              <1> 	;mov	dword [u.error], ERR_DEV_ACCESS
  2666                              <1> 	;		; permission denied ! error
  2667                              <1> otty_err: ; 13/01/2014
  2668                              <1> 	;or 	dl, dl	; DL = 0 -> called by sysstty
  2669                              <1> 	;;jnz	error
  2670                              <1> 	; 05/12/2021
  2671                              <1> 	;jz	short otty_stc_retn
  2672                              <1> 	;jmp	error
  2673                              <1> 	; 09/02/2022
  2674 00005A00 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2675 00005A03 7257                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2676                              <1> 	; iopen (dl=1 or dl=2)
  2677 00005A05 C705[ED6E0000]0B00- <1> 	mov     dword [u.error], ERR_DEV_ACCESS
  2677 00005A0D 0000                <1>
  2678                              <1> 			; permission denied ! error
  2679 00005A0F E9BEE0FFFF          <1> 	jmp	error
  2680                              <1> ;otty_stc_retn:
  2681                              <1> 	;stc
  2682                              <1> 	;retn
  2683                              <1> ottys_0:
  2684                              <1> 	; 08/01/2022
  2685                              <1> otty_ret: 
  2686                              <1> 	; 13/01/2014
  2687 00005A14 80FE07              <1> 	cmp 	dh, 7
  2688 00005A17 7624                <1> 	jna	short ottys_2
  2689                              <1> 	; 16/11/2015
  2690                              <1> com_port_check:
  2691 00005A19 BE[426B0000]        <1> 	mov	esi, com1p
  2692 00005A1E 80FE08              <1> 	cmp	dh, 8	; COM1 (tty8) ?
  2693 00005A21 7601                <1> 	jna	short ottys_1 ; yes, it is COM1
  2694 00005A23 46                  <1> 	inc	esi	; no, it is COM2 (tty9)
  2695                              <1> ottys_1:
  2696                              <1> 	; 12/11/2015
  2697 00005A24 803E00              <1> 	cmp	byte [esi], 0 ; E3h (or 23h)
  2698 00005A27 7714                <1> 	ja	short com_port_ready
  2699                              <1> 	;
  2700                              <1> 	; 09/02/2022
  2701 00005A29 80FA01              <1> 	cmp	dl, 1 ; dl = 0 ?
  2702 00005A2C 722E                <1> 	jb	short otty_retn ; yes, cf=1, called by sysstty
  2703 00005A2E C705[ED6E0000]0F00- <1>         mov     dword [u.error], ERR_DEV_NOT_RDY
  2703 00005A36 0000                <1>
  2704                              <1> 			   ; device not ready ! error
  2705                              <1> 	;jmp	short otty_err
  2706 00005A38 E995E0FFFF          <1> 	jmp	error
  2707                              <1> com_port_ready:
  2708                              <1> ottys_2:
  2709                              <1> 	; 02/03/2022
  2710                              <1> 	;or	cl, cl  ; cl = lock/owner, ch = open count
  2711                              <1> 	;jnz	short ottys_3
  2712 00005A3D 8A0D[E76E0000]      <1> 	mov	cl, [u.uno]
  2713                              <1> ottys_3:
  2714 00005A43 FEC5                <1> 	inc 	ch
  2715 00005A45 66890B              <1> 	mov 	[ebx], cx ; set tty lock again
  2716                              <1> 	; 06/12/2013
  2717 00005A48 FEC6                <1> 	inc	dh ; tty number + 1
  2718 00005A4A BB[C86E0000]        <1> 	mov	ebx, u.ttyp
  2719                              <1> 	; 13/01/2014
  2720 00005A4F F6C202              <1> 	test	dl, 2 ; open for read sign
  2721 00005A52 7501                <1> 	jnz	short ottys_4
  2722 00005A54 43                  <1> 	inc	ebx
  2723                              <1> ottys_4:
  2724                              <1> 	; Set 'u.ttyp' ('the recent TTY') value
  2725 00005A55 8833                <1> 	mov 	[ebx], dh ; tty number + 1
  2726                              <1> 	; 09/02/2022
  2727 00005A57 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  2728 00005A59 7401                <1> 	jz	short otty_retn ; 03/03/2022
  2729                              <1> sret:
  2730                              <1> 	;pop 	ax
  2731 00005A5B 58                  <1> 	pop	eax ; 08/01/2022
  2732                              <1> otty_retn:	; 09/02/2022
  2733                              <1> iclose_retn:	
  2734 00005A5C C3                  <1> 	retn
  2735                              <1> 
  2736                              <1> 	;
  2737                              <1> 	; Original UNIX v1 'otty' routine:
  2738                              <1> 	;	
  2739                              <1> 	;mov    $100,*$tks / set interrupt enable bit (zero others) in
  2740                              <1>         ;                 / reader status reg
  2741                              <1>         ;mov    $100,*$tps / set interrupt enable bit (zero others) in
  2742                              <1>         ;                 / punch status reg
  2743                              <1>         ;mov    tty+[ntty*8]-8+6,r5 / r5 points to the header of the
  2744                              <1>         ;                          / console tty buffer
  2745                              <1>         ;incb   (r5) / increment the count of processes that opened the
  2746                              <1>         ;            / console tty
  2747                              <1>         ;tst    u.ttyp / is there a process control tty (i.e., has a tty
  2748                              <1>         ;             / buffer header
  2749                              <1>         ;bne    sret / address been loaded into u.ttyp yet)?  yes, branch
  2750                              <1>         ;mov    r5,u.ttyp / no, make the console tty the process control
  2751                              <1>         ;                 / tty
  2752                              <1>         ;br     sret / ?
  2753                              <1> ;sret:
  2754                              <1> 		;clr *$ps / set processor priority to zero
  2755                              <1> ;	pop	ax
  2756                              <1>         	;mov (sp)+,r1 / pop stack to r1
  2757                              <1> ;3:
  2758                              <1> ;	retn
  2759                              <1>         	;rts r0
  2760                              <1> 	
  2761                              <1> ;ocvt:	; < open tty >
  2762                              <1> 	; 13/01/2014
  2763                              <1> 	; 06/12/2013 (major modification: p.ttyc, u.ttyp)
  2764                              <1> 	; 24/09/2013 consistency check -> ok
  2765                              <1> 	; 16/09/2013
  2766                              <1> 	; 03/09/2013
  2767                              <1> 	; 27/08/2013
  2768                              <1> 	; 16/08/2013
  2769                              <1> 	; 16/07/2013
  2770                              <1> 	; 27/05/2013
  2771                              <1> 	; 21/05/2013
  2772                              <1> 	;
  2773                              <1> 	; Retro UNIX 8086 v1 modification !
  2774                              <1> 	; 
  2775                              <1> 	; In original UNIX v1, 'ocvt' routine 
  2776                              <1> 	;	(exactly different than this one)
  2777                              <1> 	;	was in 'u9.s' file.
  2778                              <1> 	;
  2779                              <1> 	; 16/07/2013
  2780                              <1> 	; Retro UNIX 8086 v1 modification:
  2781                              <1> 	;  If a tty is open for read or write by
  2782                              <1> 	;     a process (u.uno), only same process can open
  2783                              <1> 	;     same tty to write or read (R->R&W or W->W&R).	
  2784                              <1> 	;
  2785                              <1> 	; INPUT: DL=2 for Read DL=1 for Write
  2786                              <1> 
  2787                              <1> 	; 16/09/2013
  2788                              <1> 	; sub 	al, 10
  2789                              <1> 	
  2790                              <1> 	; 06/12/2013
  2791                              <1> 	;cmp	al, 7
  2792                              <1>         ;jna     short ottyp
  2793                              <1> 	; 13/01/2014
  2794                              <1> 	;jmp	short ottyp
  2795                              <1> 
  2796                              <1> ;oppt: / open paper tape for reading or writing
  2797                              <1> ;        mov    $100,*$prs / set reader interrupt enable bit
  2798                              <1> ;        tstb   pptiflg / is file already open
  2799                              <1> ;        bne    2f / yes, branch
  2800                              <1> ;1:
  2801                              <1> ;        mov    $240,*$ps / no, set processor priority to 5
  2802                              <1> ;        jsr    r0,getc; 2 / remove all entries in clist
  2803                              <1> ;               br .+4 / for paper tape input and place in free list
  2804                              <1> ;        br     1b
  2805                              <1> ;        movb   $2,pptiflg / set pptiflg to indicate file just open
  2806                              <1> ;        movb   $10.,toutt+1 / place 10 in paper tape input tout entry
  2807                              <1> ;        br     sret
  2808                              <1> ;2:
  2809                              <1> ;        jmp    error / file already open
  2810                              <1> 
  2811                              <1> iclose:
  2812                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2813                              <1> 	; 19/05/2015
  2814                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2815                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  2816                              <1> 	;
  2817                              <1> 	; close file whose i-number is in r1
  2818                              <1> 	; 
  2819                              <1> 	; INPUTS ->
  2820                              <1> 	;    r1 - inode number
  2821                              <1> 	; OUTPUTS ->
  2822                              <1> 	;    file's inode in core	
  2823                              <1> 	;    r1 - inode number (positive)
  2824                              <1> 	;
  2825                              <1> 	; ((AX = R1))
  2826                              <1>         ;    ((Modified registers: -ebx-, edx)) 
  2827                              <1> 	;        
  2828                              <1> ;/ close file whose i-number is in r1
  2829 00005A5D B202                <1> 	mov	dl, 2 ; 12/01/2014
  2830 00005A5F F6C480              <1> 	test	ah, 80h ; Bit 15 of AX
  2831                              <1> 		; tst r1 / test i-number
  2832                              <1>         ;jnz	short iclose_2
  2833                              <1> 		; blt 2f / if neg., branch
  2834 00005A62 7405                <1> 	jz	short iclose_0 ; 30/07/2013
  2835                              <1> 	; 16/07/2013 
  2836 00005A64 66F7D8              <1> 	neg	ax ; make it positive
  2837                              <1> 	; 12/01/2014
  2838 00005A67 FECA                <1> 	dec	dl ; dl = 1 (open for write)
  2839                              <1> iclose_0:
  2840 00005A69 6683F828            <1> 	cmp	ax, 40
  2841                              <1> 		; cmp r1,$40. / is it a special file
  2842 00005A6D 77ED                <1>         ja	short iclose_retn  ; 13/01/2014
  2843                              <1> 		; bgt 3b / no, return
  2844                              <1> 	; 12/01/2014
  2845                              <1> 	; DL=2 -> special file was opened for reading
  2846                              <1> 	; DL=1 -> special file was opened for writing
  2847 00005A6F 50                  <1> 	push	eax ; 08/01/2022
  2848                              <1> 	;push	ax
  2849                              <1> 		; mov r1,-(sp) / yes, save r1 on stack
  2850 00005A70 0FB6D8              <1> 	movzx	ebx, al
  2851                              <1> 	; 08/01/2022
  2852 00005A73 C0E302              <1> 	shl	bl, 2
  2853                              <1> 	;shl	bx, 2
  2854                              <1> 		; asl r1
  2855 00005A76 81C3[7A5A0000]      <1> 	add	ebx, iclose_1 - 4
  2856 00005A7C FF23                <1> 	jmp	dword [ebx]
  2857                              <1> 		; jmp *1f-2(r1) / compute jump address and transfer
  2858                              <1> iclose_1 :
  2859 00005A7E [CA5A0000]          <1> 	dd	ctty ; tty, AX = 1 (runix)
  2860 00005A82 [255B0000]          <1> 	dd	cret ; mem, AX = 2 (runix)
  2861 00005A86 [255B0000]          <1> 	dd	cret ; fd0, AX = 3 (runix only)
  2862 00005A8A [255B0000]          <1> 	dd	cret ; fd1, AX = 4 (runix only)
  2863 00005A8E [255B0000]          <1> 	dd	cret ; hd0, AX = 5 (runix only)
  2864 00005A92 [255B0000]          <1> 	dd	cret ; hd1, AX = 6 (runix only)	
  2865 00005A96 [255B0000]          <1> 	dd	cret ; hd2, AX = 7 (runix only)
  2866 00005A9A [255B0000]          <1> 	dd	cret ; hd3, AX = 8 (runix only)	
  2867 00005A9E [255B0000]          <1> 	dd	cret ; lpr, AX = 9 (runix)
  2868                              <1> 	;dd	error; lpr, AX = 9 (error !)
  2869                              <1> 	;;dd	offset ejec ;;lpr, AX = 9  
  2870 00005AA2 [D95A0000]          <1> 	dd	ccvt ; tty0, AX = 10 (runix)	  
  2871 00005AA6 [D95A0000]          <1> 	dd	ccvt ; tty1, AX = 11 (runix)	  
  2872 00005AAA [D95A0000]          <1> 	dd	ccvt ; tty2, AX = 12 (runix)	  
  2873 00005AAE [D95A0000]          <1> 	dd	ccvt ; tty3, AX = 13 (runix)	  
  2874 00005AB2 [D95A0000]          <1> 	dd	ccvt ; tty4, AX = 14 (runix)	  
  2875 00005AB6 [D95A0000]          <1> 	dd	ccvt ; tty5, AX = 15 (runix)	  
  2876 00005ABA [D95A0000]          <1> 	dd	ccvt ; tty6, AX = 16 (runix)	  
  2877 00005ABE [D95A0000]          <1> 	dd	ccvt ; tty7, AX = 17 (runix)	  
  2878 00005AC2 [D95A0000]          <1> 	dd	ccvt ; COM1, AX = 18 (runix only)	  
  2879 00005AC6 [D95A0000]          <1> 	dd	ccvt ; COM2, AX = 19 (runix only)
  2880                              <1> 
  2881                              <1> 	; 1:
  2882                              <1> 	;        ctty   / tty
  2883                              <1> 	;        cppt   / ppt
  2884                              <1> 	;        sret   / mem
  2885                              <1> 	;        sret   / rf0
  2886                              <1> 	;        sret   / rk0
  2887                              <1> 	;        sret   / tap0
  2888                              <1> 	;        sret   / tap1
  2889                              <1> 	;        sret   / tap2
  2890                              <1> 	;        sret   / tap3
  2891                              <1> 	;        sret   / tap4
  2892                              <1> 	;        sret   / tap5
  2893                              <1> 	;        sret   / tap6
  2894                              <1> 	;        sret   / tap7
  2895                              <1> 	;        ccvt   / tty0
  2896                              <1> 	;        ccvt   / tty1
  2897                              <1> 	;        ccvt   / tty2
  2898                              <1> 	;        ccvt   / tty3
  2899                              <1> 	;        ccvt   / tty4
  2900                              <1> 	;        ccvt   / tty5
  2901                              <1> 	;        ccvt   / tty6
  2902                              <1> 	;        ccvt   / tty7
  2903                              <1> 	;        error / crd
  2904                              <1> 
  2905                              <1> ;iclose_2: ; 2: / negative i-number
  2906                              <1> 	;neg	ax
  2907                              <1> 		;neg r1 / make it positive
  2908                              <1> 	;cmp	ax, 40
  2909                              <1> 		;cmp r1,$40. / is it a special file?
  2910                              <1>         ;ja	short @b
  2911                              <1> 		;bgt    3b / no. return
  2912                              <1> 	;push	ax
  2913                              <1> 		;mov r1,-(sp)
  2914                              <1> 	;movzx	ebx, al
  2915                              <1> 	;shl	bx, 1
  2916                              <1> 		;asl r1 / yes. compute jump address and transfer
  2917                              <1> 	;add	ebx, iclose_3 - 2
  2918                              <1> 	;jmp	dword [ebx]
  2919                              <1> 		;jmp *1f-2(r1) / figure out 
  2920                              <1> ;iclose_3:
  2921                              <1> 	;dd	ctty ; tty, AX = 1 (runix)
  2922                              <1> 	;dd	sret ; mem, AX = 2 (runix)
  2923                              <1> 	;dd	sret ; fd0, AX = 3 (runix only)
  2924                              <1> 	;dd	sret ; fd1, AX = 4 (runix only)
  2925                              <1> 	;dd	sret ; hd0, AX = 5 (runix only)
  2926                              <1> 	;dd	sret ; hd1, AX = 6 (runix only)	
  2927                              <1> 	;dd	sret ; hd2, AX = 7 (runix only)
  2928                              <1> 	;dd	sret ; hd3, AX = 8 (runix only)
  2929                              <1> 	 ;dd	sret ; lpr, AX = 9	
  2930                              <1> 	;dd	ejec ; lpr, AX = 9  (runix)
  2931                              <1> 	;dd	ccvt ; tty0, AX = 10 (runix)	  
  2932                              <1> 	;dd	ccvt ; tty1, AX = 11 (runix)	  
  2933                              <1> 	;dd	ccvt ; tty2, AX = 12 (runix)	  
  2934                              <1> 	;dd	ccvt ; tty3, AX = 13 (runix)	  
  2935                              <1> 	;dd	ccvt ; tty4, AX = 14 (runix)	  
  2936                              <1> 	;dd	ccvt ; tty5, AX = 15 (runix)	  
  2937                              <1> 	;dd	ccvt ; tty6, AX = 16 (runix)	  
  2938                              <1> 	;dd	ccvt ; tty7, AX = 17 (runix)	  
  2939                              <1> 	;dd	ccvt ; COM1, AX = 18 (runix only)	  
  2940                              <1> 	;dd	ccvt ; COM2, AX = 19 (runix only) 
  2941                              <1> 	
  2942                              <1> 	;1:
  2943                              <1> 	;      	ctty   / tty
  2944                              <1> 	;       leadr  / ppt
  2945                              <1> 	;       sret   / mem
  2946                              <1> 	;       sret   / rf0
  2947                              <1> 	;       sret   / rk0
  2948                              <1> 	;       sret   / tap0
  2949                              <1> 	;       sret   / tap1
  2950                              <1> 	;       sret   / tap2
  2951                              <1> 	;       sret   / tap3
  2952                              <1> 	;       sret   / tap4
  2953                              <1> 	;       sret   / tap5
  2954                              <1> 	;       sret   / tap6
  2955                              <1> 	;       sret   / tap7
  2956                              <1> 	;       ccvt   / tty0
  2957                              <1> 	;       ccvt   / tty1
  2958                              <1> 	;       ccvt   / tty2
  2959                              <1> 	;       ccvt   / tty3
  2960                              <1> 	;       ccvt   / tty4
  2961                              <1> 	;       ccvt   / tty5
  2962                              <1> 	;       ccvt   / tty6
  2963                              <1> 	;       ccvt   / tty7
  2964                              <1> 	;/      ejec   / lpr
  2965                              <1> 
  2966                              <1> ctty: ; / close console tty
  2967                              <1> 	; 26/02/2022
  2968                              <1> 	; 09/02/2022
  2969                              <1> 	; 06/02/2022
  2970                              <1> 	; 08/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2971                              <1> 	; 18/05/2015 (Retro UNIX 386 v1 - Beginning)
  2972                              <1> 	; 21/05/2013 - 26/01/2014 (Retro UNIX 8086 v1)
  2973                              <1> 	;
  2974                              <1> 	; Retro UNIX 8086 v1 modification !
  2975                              <1> 	; (DL = 2 -> it is open for reading)
  2976                              <1> 	; (DL = 1 -> it is open for writing)
  2977                              <1> 	; (DL = 0 -> it is open for sysstty system call)
  2978                              <1> 	;
  2979                              <1> 	; 06/12/2013
  2980 00005ACA 0FB61D[E76E0000]    <1>         movzx   ebx, byte [u.uno] ; process number
  2981 00005AD1 8A83[F76B0000]      <1>         mov     al, [ebx+p.ttyc-1]
  2982                              <1> 	; 13/01/2014
  2983                              <1> 	;jmp	short cttyp
  2984                              <1> 	; 06/02/2022
  2985 00005AD7 EB04                <1> 	jmp	short ctty_0
  2986                              <1> ccvt:
  2987 00005AD9 2C0A                <1> 	sub 	al, 10
  2988                              <1> cttyp:	; (call from sysstty)
  2989                              <1> 	; 08/01/2022
  2990 00005ADB 31DB                <1> 	xor	ebx, ebx
  2991                              <1> ctty_0: ; (ebx < 256)  ; 06/02/2022
  2992                              <1> 	; 08/01/2022
  2993                              <1> 	; 18/05/2015 (32 bit modifications)
  2994                              <1> 	; 16/08/2013 - 26/01/2014
  2995                              <1> 	;movzx 	ebx, al ; tty number (0 to 9)
  2996                              <1> 	; 08/01/2022
  2997 00005ADD 88C3                <1> 	mov	bl, al
  2998 00005ADF D0E3                <1> 	shl 	bl, 1  ; aligned to word	
  2999                              <1> 	; 26/01/2014
  3000 00005AE1 81C3[246B0000]      <1> 	add 	ebx, ttyl
  3001 00005AE7 88C6                <1> 	mov 	dh, al ; tty number
  3002 00005AE9 668B03              <1> 	mov 	ax, [ebx]
  3003                              <1> 		   ; AL = lock value (0 or process number)
  3004                              <1> 		   ; AH = open count 
  3005 00005AEC 20E4                <1> 	and 	ah, ah
  3006 00005AEE 7514                <1> 	jnz	short ctty_ret
  3007                              <1>   	; 09/02/2022
  3008 00005AF0 80FA01              <1> 	cmp	dl, 1	; DL = 0 -> called by sysstty
  3009 00005AF3 7231                <1> 	jb	short ctty_stc_retn ; cf=1
  3010                              <1> 	; iclose (dl=1 or dl=2)
  3011 00005AF5 C705[ED6E0000]0A00- <1>         mov     dword [u.error], ERR_DEV_NOT_OPEN
  3011 00005AFD 0000                <1>
  3012                              <1> 			; device not open ! error
  3013                              <1> 	;jmp 	short ctty_err ; open count = 0, it is not open !
  3014 00005AFF E9CEDFFFFF          <1> 	jmp	error
  3015                              <1> 	; 26/01/2014
  3016                              <1> ctty_ret:
  3017 00005B04 FECC                <1> 	dec 	ah ; decrease open count
  3018 00005B06 7502                <1> 	jnz	short ctty_1
  3019 00005B08 30C0                <1> 	xor	al, al ; unlock/free tty
  3020                              <1> ctty_1:
  3021 00005B0A 668903              <1> 	mov 	[ebx], ax ; close tty instance
  3022                              <1> 	;
  3023 00005B0D BB[C86E0000]        <1> 	mov	ebx, u.ttyp
  3024                              <1> 	;test	dl, 1 ; open for write sign
  3025                              <1> 	;jz	short ctty_2
  3026                              <1> 	; 26/02/2022
  3027 00005B12 F6C202              <1> 	test	dl, 2 ; open for read sign
  3028 00005B15 7501                <1> 	jnz	short ctty_2
  3029 00005B17 43                  <1> 	inc	ebx
  3030                              <1> ctty_2:
  3031 00005B18 FEC6                <1> 	inc	dh ; tty number + 1
  3032 00005B1A 3A33                <1> 	cmp	dh, [ebx]
  3033                              <1> 	;jne	short cret
  3034 00005B1C 7503                <1> 	jne	short ctty_3 ; 09/02/2022
  3035                              <1> 	; Reset/Clear 'u.ttyp' ('the recent TTY') value
  3036 00005B1E C60300              <1> 	mov	byte [ebx], 0
  3037                              <1> ctty_3:
  3038                              <1> 	; 09/02/2022
  3039 00005B21 08D2                <1> 	or	dl, dl ; sysstty system call check (DL=0)
  3040 00005B23 7401                <1> 	jz	short ctty_4
  3041                              <1> cret:
  3042                              <1> 	;pop	ax
  3043                              <1> 	; 08/01/2022
  3044 00005B25 58                  <1> 	pop	eax
  3045                              <1> ctty_stc_retn:	; 09/02/2022
  3046                              <1> ctty_4:
  3047 00005B26 C3                  <1> 	retn
  3048                              <1> 
  3049                              <1> ;ctty_err: ; 13/01/2014
  3050                              <1> ;	or 	dl, dl ; DL = 0 -> called by sysstty
  3051                              <1> ;	jnz	error
  3052                              <1> ;	stc
  3053                              <1> ;	retn
  3054                              <1> 
  3055                              <1> 	; Original UNIX v1 'ctty' routine:
  3056                              <1> 	;	
  3057                              <1>         ;mov    tty+[ntty*8]-8+6,r5 
  3058                              <1> 	;		;/ point r5 to the console tty buffer
  3059                              <1>         ;decb   (r5) / dec number of processes using console tty
  3060                              <1>         ;br     sret / return via sret
  3061                              <1> 
  3062                              <1> ;ccvt:	; < close tty >
  3063                              <1> 	; 21/05/2013 - 13/01/2014 (Retro UNIX 8086 v1)
  3064                              <1> 	;
  3065                              <1> 	; Retro UNIX 8086 v1 modification !
  3066                              <1> 	; 
  3067                              <1> 	; In original UNIX v1, 'ccvt' routine 
  3068                              <1> 	;		(exactly different than this one)
  3069                              <1> 	;	was in 'u9.s' file.
  3070                              <1> 	;
  3071                              <1> 	; DL = 2 -> it is open for reading
  3072                              <1> 	; DL = 1 -> it is open for writing
  3073                              <1> 	;
  3074                              <1> 	; 17/09/2013
  3075                              <1> 	;sub 	al, 10
  3076                              <1> 	;cmp	al, 7
  3077                              <1> 	;jna	short cttyp
  3078                              <1> 	; 13/01/2014
  3079                              <1> 	;jmp	short cttyp
  3080                              <1> 
  3081                              <1> ;cppt: / close paper tape
  3082                              <1> ;        clrb   pptiflg / set pptiflg to indicate file not open
  3083                              <1> ;1:
  3084                              <1> ;        mov    $240,*$ps /set process or priority to 5
  3085                              <1> ;        jsr    r0,getc; 2 / remove all ppt input entries from clist
  3086                              <1> ;                          / and assign to free list
  3087                              <1> ;               br sret
  3088                              <1> ;        br     1b
  3089                              <1> 
  3090                              <1> ;ejec:	
  3091                              <1> ;	jmp	error
  3092                              <1> ;/ejec:
  3093                              <1> ;/       mov    $100,*$lps / set line printer interrupt enable bit
  3094                              <1> ;/       mov    $14,r1 / 'form feed' character in r1 (new page).
  3095                              <1> ;/       jsr    r0,lptoc / space the printer to a new page
  3096                              <1> ;/       br     sret / return to caller via 'sret'
  2103                                  %include 'u8.s'        ; 11/06/2015
  2104                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS8.INC
  2105                              <1> ; Last Modification: 12/02/2022
  2106                              <1> ; ----------------------------------------------------------------------------
  2107                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2108                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2109                              <1> ;
  2110                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2111                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2112                              <1> ; <Bell Laboratories (17/3/1972)>
  2113                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2114                              <1> ;
  2115                              <1> ; Retro UNIX 8086 v1 - U8.ASM (18/01/2014) //// UNIX v1 -> u8.s
  2116                              <1> ;
  2117                              <1> ; ****************************************************************************
  2118                              <1> 
  2119                              <1> ;; I/O Buffer - Retro UNIX 386 v1 modification
  2120                              <1> ;;     (8+512 bytes, 8 bytes header, 512 bytes data)
  2121                              <1> ;; Word 1, byte 0 = device id
  2122                              <1> ;; Word 1, byte 1 = status bits (bits 8 to 15)
  2123                              <1> ;;          bit 9 = write bit
  2124                              <1> ;;	    bit 10 = read bit	  
  2125                              <1> ;;	    bit 12 = waiting to write bit	
  2126                              <1> ;;	    bit 13 = waiting to read bit
  2127                              <1> ;;	    bit 15 = inhibit bit
  2128                              <1> ;; Word 2 (byte 2 & byte 3) = reserved (for now - 07/06/2015)
  2129                              <1> ;; Word 3 + Word 4 (byte 4,5,6,7) = physical block number 
  2130                              <1> ;;		   (In fact, it is 32 bit LBA for Retro UNIX 386 v1)
  2131                              <1> ;;
  2132                              <1> ;; I/O Buffer ((8+512 bytes in original Unix v1))
  2133                              <1> ;;	      ((4+512 bytes in Retro UNIX 8086 v1))
  2134                              <1> ;;
  2135                              <1> ;; I/O Queue Entry (of original UNIX operating system v1)
  2136                              <1> ;; Word 1, Byte 0 = device id
  2137                              <1> ;; Word 1, Byte 1 = (bits 8 to 15)
  2138                              <1> ;;          bit 9 = write bit
  2139                              <1> ;;	    bit 10 = read bit	  
  2140                              <1> ;;	    bit 12 = waiting to write bit	
  2141                              <1> ;;	    bit 13 = waiting to read bit
  2142                              <1> ;;	    bit 15 = inhibit bit
  2143                              <1> ;; Word 2 = physical block number (In fact, it is LBA for Retro UNIX 8086 v1)
  2144                              <1> ;;
  2145                              <1> ;; Original UNIX v1 ->
  2146                              <1> ;;		Word 3 = number of words in buffer (=256) 		
  2147                              <1> ;; Original UNIX v1 -> 
  2148                              <1> ;;		Word 4 = bus address (addr of first word of data buffer)
  2149                              <1> ;;
  2150                              <1> ;; Retro UNIX 8086 v1 -> Buffer Header (I/O Queue Entry) size is 4 bytes !
  2151                              <1> ;;
  2152                              <1> ;; Device IDs (of Retro Unix 8086 v1)
  2153                              <1> ;;          0 = fd0
  2154                              <1> ;;	    1 = fd1
  2155                              <1> ;;	    2 = hd0
  2156                              <1> ;;	    3 = hd1
  2157                              <1> ;;	    4 = hd2
  2158                              <1> ;;	    5 = hd3
  2159                              <1> 
  2160                              <1> ; Retro UNIX 386 v1 - 32 bit modifications (rfd, wfd, rhd, whd) - 09/06/2015
  2161                              <1> 
  2162                              <1> 	; 08/02/2022
  2163                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2164                              <1> rfd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2165                              <1> 	; 26/04/2013
  2166                              <1>    	; 13/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2167                              <1>    	;sub 	ax, 3 ; zero based device number (Floppy disk)
  2168                              <1>       	;jmp 	short bread ; **** returns to routine that called readi			
  2169                              <1> 
  2170                              <1> 	; 08/02/2022
  2171                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2172                              <1> rhd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2173                              <1> 	; 26/04/2013
  2174                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2175                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2176                              <1>    	;jmp	short bread ; **** returns to routine that called readi	
  2177                              <1> 
  2178                              <1> bread: 
  2179                              <1> 	; 08/02/2022
  2180                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2181                              <1> 	; 14/07/2015
  2182                              <1> 	; 10/07/2015
  2183                              <1> 	; 09/06/2015
  2184                              <1> 	; 07/06/2015 (Retro UNIX 386 v1 - Beginning)
  2185                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2186                              <1> 	;	
  2187                              <1> 	; / read a block from a block structured device
  2188                              <1> 	;
  2189                              <1> 	; INPUTS ->
  2190                              <1> 	;    [u.fofp] points to the block number
  2191                              <1> 	;    CX = maximum block number allowed on device
  2192                              <1> 	;	 ; that was an arg to bread, in original Unix v1, but
  2193                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2194                              <1> 	;    [u.count]	number of bytes to read in
  2195                              <1> 	; OUTPUTS ->
  2196                              <1> 	;    [u.base] starting address of data block or blocks in user area  	
  2197                              <1> 	;    [u.fofp] points to next consecutive block to be read
  2198                              <1> 	;
  2199                              <1> 	; ((Modified registers: eAX, eDX, eCX, eBX, eSI, eDI, eBP))
  2200                              <1> 	;
  2201                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if read
  2202                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2203                              <1> 	;	is increased by 1. For example: If user/program request 
  2204                              <1> 	;       to read 16 bytes in current block, 'sys read' increases
  2205                              <1> 	;  	the next block number just as 512 byte reading is done.
  2206                              <1> 	;       This wrong is done in 'bread'. So, in Retro UNIX 8086 v1, 
  2207                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2208                              <1> 	;       enough to keep byte position/offset of the disk), this
  2209                              <1> 	;	defect will not be corrected, user/program must request
  2210                              <1> 	;	512 byte read per every 'sys read' call to block devices
  2211                              <1> 	;       for achieving correct result. In future version(s), 
  2212                              <1> 	;	this defect will be corrected by using different 
  2213                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2214                              <1> 
  2215                              <1> 	   	; jsr r0,tstdeve / error on special file I/O 
  2216                              <1> 			       ; / (only works on tape)
  2217                              <1> 		; mov *u.fofp,r1 / move block number to r1
  2218                              <1> 		; mov $2.-cold,-(sp) / "2-cold" to stack
  2219                              <1> ;1:
  2220                              <1> 		; cmp r1,(r0) / is this block # greater than or equal to
  2221                              <1> 			    ; / maximum block # allowed on device
  2222                              <1> 		; jnb short @f
  2223                              <1> 		; bhis	1f / yes, 1f (error)
  2224                              <1> 		; mov r1,-(sp) / no, put block # on stack
  2225                              <1> 		; jsr r0,preread / read in the block into an I/O buffer
  2226                              <1> 		; mov (sp)+,r1 / return block # to r1
  2227                              <1> 		; inc r1 / bump block # to next consecutive block
  2228                              <1> 		; dec (sp) / "2-1-cold" on stack
  2229                              <1> 		; bgt 1b / 2-1-cold = 0?  No, go back and read in next block
  2230                              <1> ;1:
  2231                              <1> 		; tst (sp)+ / yes, pop stack to clear off cold calculation
  2232                              <1> 	;push	ecx ; **
  2233                              <1> 	; 26/04/2013
  2234                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2235 00005B27 2C03                <1> 	sub	al, 3
  2236                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2237 00005B29 A2[006F0000]        <1> 	mov	[u.brwdev], al
  2238                              <1> 	; 09/06/2015
  2239                              <1> 	;movzx	ebx, al
  2240                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2241                              <1> 	; 12/01/2022 (BugFix)
  2242 00005B2E C0E002              <1> 	shl	al, 2 ; * 4
  2243 00005B31 8B88[FE650000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2244                              <1> bread_0:
  2245 00005B37 51                  <1> 	push	ecx ; ** ; 09/06/2015 
  2246                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2247                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2248 00005B38 8B1D[A86E0000]      <1> 	mov	ebx, [u.fofp]
  2249 00005B3E 8B03                <1> 	mov	eax, [ebx]
  2250 00005B40 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2251                              <1> 		; mov *u.fofp,r1 / restore r1 to initial value of the
  2252                              <1> 			       ; / block #
  2253 00005B43 39C8                <1> 	cmp	eax, ecx
  2254                              <1> 		; cmp r1,(r0)+ / block # greater than or equal to maximum
  2255                              <1>        	                     ; / block number allowed
  2256                              <1> 	;jnb	error 	     ; 18/04/2013
  2257                              <1> 		; bhis error10 / yes, error
  2258                              <1> 	; 08/02/2022
  2259                              <1> 	;jb	short bread_1
  2260                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2261                              <1> 	;jmp	error
  2262 00005B45 735A                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2263                              <1> bread_1:
  2264                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2265                              <1> 		; inc *u.fofp / no, *u.fofp has next block number
  2266                              <1> 	; eAX = Block number (zero based)
  2267                              <1> 		;;jsr r0,preread / read in the block whose number is in r1
  2268                              <1> preread: ;; call preread
  2269 00005B47 BF[006F0000]        <1> 	mov	edi, u.brwdev ; block device number for direct I/O
  2270 00005B4C E888020000          <1> 	call	bufaloc_0 ; 26/04/2013
  2271                              <1> 	;; jc 	error
  2272                              <1> 	; eBX = Buffer (Header) Address -Physical-
  2273                              <1>         ; eAX = Block/Sector number (r1)
  2274                              <1> 	       ; jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
  2275                              <1> 	; 14/03/2013
  2276 00005B51 7411                <1>         jz	short bread_2 ; Retro UNIX 8086 v1 modification
  2277                              <1>        		; br 1f / branch if block already in a I/O buffer
  2278 00005B53 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2279                              <1>         	; bis $2000,(r5) / set read bit (bit 10 in I/O buffer)
  2280 00005B58 E8DA010000          <1> 	call	poke
  2281                              <1>         	; jsr r0,poke / perform the read
  2282                              <1> 	;;jc	error ;2 0/07/2013
  2283                              <1> ; 1:
  2284                              <1>  		; clr *$ps / ps = 0
  2285                              <1>         	; rts r0
  2286                              <1> 	; 08/02/2022
  2287 00005B5D 7305                <1> 	jnc	short bread_2
  2288 00005B5F E937010000          <1> 	jmp	dskrd_err
  2289                              <1> 	;
  2290                              <1> ;; return from preread
  2291                              <1> bread_2:
  2292 00005B64 66810B0040          <1> 	or	word [ebx], 4000h 
  2293                              <1> 		; bis $40000,(r5) 
  2294                              <1> 			; / set bit 14 of the 1st word of the I/O buffer
  2295                              <1> bread_3: ; 1:
  2296 00005B69 66F7030024          <1> 	test	word [ebx], 2400h
  2297                              <1> 		; bit $22000,(r5) / are 10th and 13th bits set (read bits)
  2298 00005B6E 7407                <1> 	jz	short bread_4
  2299                              <1> 		; beq 1f / no
  2300                              <1> 		; cmp cdev,$1 / disk or drum?
  2301                              <1> 		; ble 2f / yes
  2302                              <1> 		; tstb uquant / is the time quantum = 0?
  2303                              <1> 		; bne 2f / no, 2f
  2304                              <1> 		; mov r5,-(sp) / yes, save r5 (buffer address)
  2305                              <1> 		; jsr r0,sleep; 31. 
  2306                              <1> 			; / put process to sleep in channel 31 (tape)
  2307                              <1> 		; mov (sp)+,r5 / restore r5
  2308                              <1> 		; br 1b / go back
  2309                              <1> ; 2: / drum or disk
  2310                              <1>         ;; mov	cx, [s.wait_]+2 ;; 29/07/2013
  2311 00005B70 E8B7F3FFFF          <1> 	call	idle
  2312                              <1> 		; jsr r0,idle; s.wait+2 / wait
  2313 00005B75 EBF2                <1> 	jmp	short bread_3
  2314                              <1>        		; br 1b
  2315                              <1> bread_4: ; 1: / 10th and 13th bits not set
  2316 00005B77 668123FFBF          <1> 	and	word [ebx], 0BFFFh ; 1011111111111111b
  2317                              <1> 		; bic $40000,(r5) / clear bit 14
  2318                              <1>        		; jsr r0,tstdeve / test device for error (tape)
  2319 00005B7C 83C308              <1> 	add	ebx, 8
  2320                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2321                              <1> 	; 09/06/2015
  2322 00005B7F 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0
  2323 00005B87 7705                <1> 	ja	short bread_5
  2324 00005B89 E875F9FFFF          <1> 	call	trans_addr_w ; translate virtual address to physical (w)
  2325                              <1> bread_5:
  2326                              <1> 	; eBX = system (I/O) buffer address
  2327 00005B8E E870000000          <1> 	call	dioreg
  2328                              <1>        		; jsr r0,dioreg / do bookkeeping on u.count etc.
  2329                              <1> 	; esi = start address of the transfer (in the buffer)
  2330                              <1> 	; edi = [u.pbase], destination address in user's memory space
  2331                              <1> 	; ecx = transfer count (in bytes)
  2332                              <1> 	;
  2333                              <1> ;1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
  2334                              <1> ;   / of users data
  2335 00005B93 F3A4                <1> 	rep	movsb
  2336                              <1> 		; movb (r5)+,(r2)+ / move data from the I/O buffer
  2337                              <1>        		; dec r3 / to the user's area in core starting at u.base
  2338                              <1>        		; bne 1b
  2339 00005B95 59                  <1> 	pop	ecx ; **
  2340 00005B96 833D[BC6E0000]00    <1> 	cmp	dword [u.count], 0
  2341                              <1> 		; tst u.count / done
  2342 00005B9D 7798                <1> 	ja	short bread_0 ; 09/06/2015
  2343                              <1>        		; beq 1f / yes, return
  2344                              <1> 		; tst -(r0) / no, point r0 to the argument again
  2345                              <1>        		; br bread / read some more
  2346                              <1> ; 1:
  2347 00005B9F 58                  <1> 	pop	eax ; ****
  2348                              <1>        		; mov (sp)+,r0
  2349 00005BA0 C3                  <1>         retn		; 09/06/2015
  2350                              <1> 	;jmp	ret_ 
  2351                              <1> 		;jmp ret  / jump to routine that called readi
  2352                              <1> 
  2353                              <1> 	; 08/02/2022
  2354                              <1> brw_oov_err:
  2355 00005BA1 C705[ED6E0000]1000- <1> 	mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2355 00005BA9 0000                <1>
  2356 00005BAB E922DFFFFF          <1> 	jmp	error
  2357                              <1> 
  2358                              <1> 	; 08/02/2022
  2359                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2360                              <1> wfd:    ; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2361                              <1> 	; 26/04/2013
  2362                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2363                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2364                              <1>    	;jmp	short bwrite ; **** returns to routine that called writei
  2365                              <1> 
  2366                              <1> 
  2367                              <1> 	; 08/02/2022
  2368                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)				
  2369                              <1> whd:	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2370                              <1>    	; 14/03/2013 Retro UNIX 8086 v1 device (not an original unix v1 device)	
  2371                              <1>    	;sub 	ax, 3 ; zero based device number (Hard disk)
  2372                              <1>    	;jmp 	short bwrite ; **** returns to routine that called writei ('jmp ret')
  2373                              <1> 
  2374                              <1> bwrite:
  2375                              <1> 	; 08/02/2022
  2376                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2377                              <1> 	; 14/07/2015
  2378                              <1> 	; 10/07/2015
  2379                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2380                              <1> 	; 14/03/2013 - 20/07/2013 (Retro UNIX 8086 v1)
  2381                              <1> 	;	
  2382                              <1> 	;; / write on block structured device
  2383                              <1> 	;
  2384                              <1> 	; INPUTS ->
  2385                              <1> 	;    [u.fofp] points to the block number
  2386                              <1> 	;    CX = maximum block number allowed on device
  2387                              <1> 	;	 ; that was an arg to bwrite, in original Unix v1, but
  2388                              <1> 	;	 ; CX register is used instead of arg in Retro Unix 8086 v1 		
  2389                              <1> 	;    [u.count]	number of bytes to user desires to write
  2390                              <1> 	; OUTPUTS ->
  2391                              <1> 	;    [u.fofp] points to next consecutive block to be written into
  2392                              <1> 	;
  2393                              <1> 	; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))
  2394                              <1> 	;
  2395                              <1> 	; NOTE: Original UNIX v1 has/had a defect/bug here, even if write
  2396                              <1> 	;       byte count is less than 512, block number in *u.fofp (u.off)
  2397                              <1> 	;	is increased by 1. For example: If user/program request 
  2398                              <1> 	;       to write 16 bytes in current block, 'sys write' increases
  2399                              <1> 	;  	the next block number just as 512 byte writing is done.
  2400                              <1> 	;       This wrong is done in 'bwrite'. So, in Retro UNIX 8086 v1, 
  2401                              <1> 	;       for user (u) structure compatibility (because 16 bit is not
  2402                              <1> 	;       enough to keep byte position/offset of the disk), this
  2403                              <1> 	;	defect will not be corrected, user/program must request
  2404                              <1> 	;	512 byte write per every 'sys write' call to block devices
  2405                              <1> 	;       for achieving correct result. In future version(s), 
  2406                              <1> 	;	this defect will be corrected by using different 
  2407                              <1> 	;       user (u) structure. 26/07/2013 - Erdogan Tan 	
  2408                              <1> 
  2409                              <1>        		; jsr r0,tstdeve / test the device for an error
  2410                              <1> 	;push	ecx ; **
  2411                              <1> 	; 26/04/2013
  2412                              <1> 	;sub	ax, 3 ; 3 to 8 -> 0 to 5
  2413 00005BB0 2C03                <1> 	sub	al, 3
  2414                              <1> 		; AL = Retro Unix 8086 v1 disk (block device) number
  2415 00005BB2 A2[006F0000]        <1> 	mov	[u.brwdev], al
  2416                              <1> 	; 09/06/2015
  2417                              <1> 	;movzx	ebx, al
  2418                              <1> 	;mov	ecx, [ebx+drv.size] ; disk size (in sectors)
  2419                              <1> 	; 12/01/2022 (BugFix)
  2420 00005BB7 C0E002              <1> 	shl	al, 2 ; * 4
  2421 00005BBA 8B88[FE650000]      <1> 	mov	ecx, [eax+drv.size] ; disk size (in sectors)
  2422                              <1> bwrite_0:
  2423 00005BC0 51                  <1> 	push	ecx ; ** ; 09/06/2015
  2424                              <1> 	; 10/07/2015 (Retro UNIX 386 v1 modification!)
  2425                              <1> 	; [u.fofp] points to byte position in disk, not sector/block !
  2426 00005BC1 8B1D[A86E0000]      <1> 	mov	ebx, [u.fofp]
  2427 00005BC7 8B03                <1> 	mov	eax, [ebx]       
  2428 00005BC9 C1E809              <1> 	shr	eax, 9 ; convert byte position to block/sector number
  2429                              <1> 		; mov *u.fofp,r1 / put the block number in r1
  2430 00005BCC 39C8                <1> 	cmp	eax, ecx
  2431                              <1> 		; cmp r1,(r0)+ / does block number exceed maximum allowable #
  2432                              <1>        	                     ; / block number allowed
  2433                              <1> 	;jnb	error	     ; 18/04/2013
  2434                              <1> 		; bhis error10 / yes, error
  2435                              <1>      	; 08/02/2022
  2436                              <1> 	;jb	short bwrite_1
  2437                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE  ; 'out of volume' error
  2438                              <1> 	;jmp	error
  2439 00005BCE 73D1                <1> 	jnb	short brw_oov_err ; 'out of volume' error
  2440                              <1> bwrite_1:
  2441                              <1> 	;inc 	dword [ebx] ; 10/07/2015 (Retro UNIX 386 v1 - modification!)
  2442                              <1> 		; inc *u.fofp / no, increment block number
  2443                              <1> 	; 09/06/2015 - 10/07/2015
  2444 00005BD0 66833D[FD6E0000]00  <1> 	cmp	word [u.pcount], 0
  2445 00005BD8 7705                <1> 	ja	short bwrite_2
  2446 00005BDA E820F9FFFF          <1> 	call	trans_addr_r ; translate virtual address to physical (r)
  2447                              <1> bwrite_2:
  2448 00005BDF BF[006F0000]        <1> 	mov	edi, u.brwdev  ; block device number for direct I/O
  2449 00005BE4 E8D3000000          <1>        	call	bwslot ; 26/04/2013 (wslot -> bwslot)	 				
  2450                              <1> 		; jsr r0,wslot / get an I/O buffer to write into
  2451                              <1> 		; add $8,r5 / r5 points to data in I/O buffer
  2452 00005BE9 E815000000          <1>         call	dioreg
  2453                              <1> 		; jsr r0,dioreg / do the necessary bookkeeping
  2454                              <1> 	; esi = destination address (in the buffer)
  2455                              <1> 	; edi = [u.pbase], start address of transfer in user's memory space
  2456                              <1> 	; ecx = transfer count (in bytes)
  2457                              <1> ; 1: / r2 points to the users data; r5 points to the I/O buffers data area
  2458 00005BEE 87F7                <1> 	xchg 	esi, edi ; 14/07/2015
  2459 00005BF0 F3A4                <1> 	rep	movsb
  2460                              <1> 		; movb (r2)+,(r5)+ / ; r3, has the byte count
  2461                              <1>        		; dec r3 / area to the I/O buffer
  2462                              <1>        		; bne 1b
  2463 00005BF2 E80D010000          <1> 	call	dskwr
  2464                              <1> 		; jsr r0,dskwr / write it out on the device
  2465 00005BF7 59                  <1> 	pop	ecx ; **
  2466 00005BF8 833D[BC6E0000]00    <1>         cmp     dword [u.count], 0
  2467                              <1> 		; tst u.count / done
  2468 00005BFF 77BF                <1> 	ja	short bwrite_0 ; 09/06/2015
  2469                              <1> 		; beq 1f / yes, 1f
  2470                              <1> 		; tst -(r0) / no, point r0 to the argument of the call
  2471                              <1>        		; br bwrite / go back and write next block
  2472                              <1> ; 1:
  2473 00005C01 58                  <1> 	pop	eax ; ****
  2474                              <1>        		; mov (sp)+,r0
  2475 00005C02 C3                  <1> 	retn		; 09/06/2015
  2476                              <1>         ;jmp	ret_ 
  2477                              <1> 		; jmp ret / return to routine that called writei
  2478                              <1> ;error10:
  2479                              <1> ;       jmp     error  ; / see 'error' routine
  2480                              <1> 
  2481                              <1> dioreg:
  2482                              <1> 	; 04/02/2022
  2483                              <1> 	; 14/07/2015
  2484                              <1> 	; 10/07/2015 (UNIX v1 bugfix - [u.fofp]: byte pos., not block)
  2485                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2486                              <1> 	; 14/03/2013 (Retro UNIX 8086 v1)
  2487                              <1> 	;	
  2488                              <1> 	; bookkeeping on block transfers of data
  2489                              <1> 	;
  2490                              <1> 	; * returns value of u.pbase before it gets updated, in EDI
  2491                              <1> 	; * returns byte count (to transfer) in ECX (<=512)
  2492                              <1> 	; 10/07/2015
  2493                              <1> 	; * returns byte offset from beginning of current sector buffer
  2494                              <1> 	; (beginning of data) in ESI
  2495                              <1> 	;
  2496 00005C03 8B0D[BC6E0000]      <1> 	mov	ecx, [u.count]
  2497                              <1> 		; mov u.count,r3 / move char count to r3
  2498                              <1> 	; 04/02/2022
  2499 00005C09 31D2                <1> 	xor	edx, edx
  2500 00005C0B B602                <1> 	mov	dh, 2
  2501                              <1> 	; edx = 512
  2502 00005C0D 39D1                <1> 	cmp	ecx, edx ; 512
  2503                              <1> 	;cmp 	ecx, 512
  2504                              <1> 		; cmp r3,$512. / more than 512. char?
  2505 00005C0F 7602                <1> 	jna	short dioreg_0
  2506                              <1> 		; blos 1f / no, branch
  2507 00005C11 89D1                <1> 	mov	ecx, edx ; 512
  2508                              <1> 	;mov	ecx, 512
  2509                              <1> 		; mov $512.,r3 / yes, just take 512.
  2510                              <1> dioreg_0:
  2511                              <1> 	; 09/06/2015
  2512 00005C13 663B0D[FD6E0000]    <1> 	cmp	cx, [u.pcount]
  2513 00005C1A 7607                <1> 	jna	short dioreg_1
  2514 00005C1C 668B0D[FD6E0000]    <1> 	mov	cx, [u.pcount]
  2515                              <1> dioreg_1:
  2516                              <1> ; 1:
  2517 00005C23 8B15[B86E0000]      <1> 	mov	edx, [u.base] ; 09/06/2015 (eax -> edx)
  2518                              <1> 	        ; mov u.base,r2 / put users base in r2
  2519 00005C29 010D[C06E0000]      <1> 	add	[u.nread], ecx
  2520                              <1> 		; add r3,u.nread / add the number to be read to u.nread
  2521 00005C2F 290D[BC6E0000]      <1> 	sub	[u.count], ecx
  2522                              <1> 		; sub r3,u.count / update count
  2523 00005C35 010D[B86E0000]      <1> 	add	[u.base], ecx
  2524                              <1> 		; add r3,u.base / update base
  2525                              <1> 	; 10/07/2015
  2526                              <1> 	; Retro UNIX 386 v1 - modification !
  2527                              <1> 	; (File pointer points to byte position, not block/sector no.)
  2528                              <1> 	; (It will point to next byte position instead of next block no.)
  2529 00005C3B 8B35[A86E0000]      <1> 	mov	esi, [u.fofp] ; u.fopf points to byte position pointer  
  2530 00005C41 8B06                <1> 	mov	eax, [esi] ; esi points to current byte pos. on the disk
  2531 00005C43 010E                <1> 	add	[esi], ecx ; ecx is added to set the next byte position
  2532 00005C45 25FF010000          <1> 	and	eax, 1FFh  ; get offset from beginning of current block	
  2533 00005C4A 89DE                <1> 	mov	esi, ebx   ; beginning of data in sector/block buffer
  2534 00005C4C 01C6                <1> 	add	esi, eax   ; esi contains start address of the transfer
  2535                              <1> 	; 09/06/2015 - 10/07/2015
  2536 00005C4E 66290D[FD6E0000]    <1> 	sub	[u.pcount], cx
  2537 00005C55 81E2FF0F0000        <1> 	and	edx, PAGE_OFF ; 0FFFh
  2538 00005C5B 8B3D[F96E0000]      <1> 	mov	edi, [u.pbase]
  2539 00005C61 81E700F0FFFF        <1> 	and	edi, ~PAGE_OFF
  2540 00005C67 01D7                <1> 	add	edi, edx
  2541 00005C69 893D[F96E0000]      <1> 	mov	[u.pbase], edi
  2542 00005C6F 010D[F96E0000]      <1> 	add	[u.pbase], ecx ; 14/07/2015
  2543 00005C75 C3                  <1> 	retn
  2544                              <1> 		; rts r0 / return
  2545                              <1> 
  2546                              <1> dskrd:
  2547                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2548                              <1> 	; 18/08/2015
  2549                              <1> 	; 02/07/2015
  2550                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2551                              <1> 	; 14/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2552                              <1> 	;
  2553                              <1> 	; 'dskrd' acquires an I/O buffer, puts in the proper
  2554                              <1> 	; I/O queue entries (via bufaloc) then reads a block
  2555                              <1> 	; (number specified in r1) in the acquired buffer.)
  2556                              <1> 	; If the device is busy at the time dskrd is called,	
  2557                              <1> 	; dskrd calls idle.
  2558                              <1> 	; 
  2559                              <1> 	; INPUTS ->
  2560                              <1> 	;    r1 - block number
  2561                              <1> 	;    cdev - current device number 
  2562                              <1> 	; OUTPUTS ->
  2563                              <1> 	;    r5 - points to first data word in I/O buffer
  2564                              <1> 	;
  2565                              <1> 	; ((AX = R1)) input/output
  2566                              <1> 	; ((BX = R5)) output 
  2567                              <1> 	;
  2568                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP))  
  2569                              <1> 	;
  2570 00005C76 E851010000          <1> 	call 	bufaloc
  2571                              <1> 		; jsr r0,bufaloc / shuffle off to bufaloc; 
  2572                              <1> 			       ; / get a free I/O buffer
  2573                              <1> 	;;jc	error ; 20/07/2013
  2574 00005C7B 740C                <1> 	jz	short dskrd_1 ; Retro UNIX 8086 v1 modification
  2575                              <1>        		; br 1f / branch if block already in a I/O buffer
  2576                              <1> dskrd_0: ; 10/07/2015 (wslot)
  2577 00005C7D 66810B0004          <1> 	or	word [ebx], 400h ; set read bit (10) in I/O Buffer
  2578                              <1>         	; bis $2000,(r5) / set bit 10 of word 1 of 
  2579                              <1> 		               ; / I/O queue entry for buffer
  2580 00005C82 E8B0000000          <1> 	call	poke
  2581                              <1> 		; jsr r0,poke / just assigned in bufaloc, 
  2582                              <1> 			    ; /	bit 10=1 says read
  2583                              <1> 	; 09/06/2015
  2584                              <1> 	;jnc	short dskrd_1
  2585                              <1> 	;mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2586                              <1> 	;jmp	error
  2587                              <1> 	; 08/02/2022
  2588 00005C87 7212                <1> 	jc	short dskrd_3
  2589                              <1> dskrd_1: ; 1:
  2590                              <1>        		;clr *$ps
  2591 00005C89 66F7030024          <1>        	test	word [ebx], 2400h
  2592                              <1> 		; bit $22000,(r5) / if either bits 10, or 13 are 1; 
  2593                              <1> 				; / jump to idle
  2594 00005C8E 7407                <1>        	jz	short dskrd_2
  2595                              <1> 		; beq 1f
  2596                              <1>         ;;mov   ecx, [s.wait_]
  2597 00005C90 E897F2FFFF          <1>        	call	idle
  2598                              <1> 		; jsr r0,idle; s.wait+2
  2599 00005C95 EBF2                <1> 	jmp 	short dskrd_1
  2600                              <1>        		; br 1b
  2601                              <1> dskrd_2: ; 1:
  2602 00005C97 83C308              <1>         add	ebx, 8
  2603                              <1> 		; add $8,r5 / r5 points to first word of data in block 
  2604                              <1> 			  ; / just read in
  2605 00005C9A C3                  <1>        	retn
  2606                              <1> 		; rts r0
  2607                              <1> dskrd_err: 
  2608                              <1> 	; 08/02/2022
  2609                              <1> 	; (jump from 'bread' error)	
  2610                              <1> dskrd_3:	
  2611                              <1> 	; 08/02/2022
  2612 00005C9B 803D[006F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2613 00005CA2 7509                <1> 	jne	short dskrd_4 ; no
  2614                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2615 00005CA4 C605[006F0000]00    <1> 	mov	byte [u.brwdev], 0
  2616 00005CAB EB0A                <1> 	jmp	short dskrd_5
  2617                              <1> dskrd_4:
  2618 00005CAD C705[ED6E0000]1100- <1> 	mov	dword [u.error], ERR_DRV_READ ; disk read error !
  2618 00005CB5 0000                <1>
  2619                              <1> dskrd_5:
  2620 00005CB7 E916DEFFFF          <1> 	jmp	error
  2621                              <1> 
  2622                              <1> bwslot:
  2623                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2624                              <1> 	; 10/07/2015
  2625                              <1> 	;	If the block/sector is not placed in a buffer
  2626                              <1> 	;	before 'wslot', it must be read before
  2627                              <1> 	;	it is written! (Otherwise transfer counts less
  2628                              <1> 	;	than 512 bytes will be able to destroy existing 
  2629                              <1> 	;	data on disk.)
  2630                              <1> 	;
  2631                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2632                              <1> 	; 26/04/2013(Retro UNIX 8086 v1)
  2633                              <1> 	; Retro UNIX 8086 v1 modification !
  2634                              <1> 	; ('bwslot' will be called from 'bwrite' only!)
  2635                              <1> 	; INPUT -> eDI - points to device id (in u.brwdev)	
  2636                              <1> 	;	-> eAX = block number
  2637                              <1> 	;
  2638 00005CBC E818010000          <1> 	call	bufaloc_0
  2639 00005CC1 742A                <1> 	jz	short wslot_0 ; block/sector already is in the buffer
  2640                              <1> 	; 12/01/2022
  2641                              <1> 	; ebx = buffer header address
  2642                              <1> bwslot_0:
  2643                              <1> 	; 10/07/2015
  2644 00005CC3 8B35[A86E0000]      <1> 	mov	esi, [u.fofp]
  2645 00005CC9 8B06                <1> 	mov	eax, [esi]
  2646 00005CCB 25FF010000          <1> 	and	eax, 1FFh ; offset from beginning of the sector/block
  2647 00005CD0 750C                <1> 	jnz 	short bwslot_1 ; it is not a full sector write
  2648                              <1> 		       ; recent disk data must be placed in the buffer
  2649 00005CD2 813D[BC6E0000]0002- <1> 	cmp	dword [u.count], 512
  2649 00005CDA 0000                <1>
  2650 00005CDC 730F                <1> 	jnb	short wslot_0	
  2651                              <1> bwslot_1:
  2652 00005CDE E89AFFFFFF          <1> 	call	dskrd_0
  2653                              <1> 	; 12/01/2022
  2654                              <1> 	; ebx = buffer data address = buffer header address + 8
  2655 00005CE3 83EB08              <1> 	sub	ebx, 8 ; set ebx to the buffer header address again
  2656 00005CE6 EB05                <1> 	jmp 	short wslot_0
  2657                              <1> 
  2658                              <1> wslot:
  2659                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2660                              <1> 	; 		(32 bit modifications)
  2661                              <1> 	; 14/03/2013 - 29/07/2013(Retro UNIX 8086 v1)
  2662                              <1> 	;
  2663                              <1> 	; 'wslot' calls 'bufaloc' and obtains as a result, a pointer
  2664                              <1> 	; to the I/O queue of an I/O buffer for a block structured
  2665                              <1> 	; device. It then checks the first word of I/O queue entry.	
  2666                              <1> 	; If bits 10 and/or 13 (read bit, waiting to read bit) are set,
  2667                              <1> 	; wslot calls 'idle'. When 'idle' returns, or if bits 10 
  2668                              <1> 	; and/or 13 are not set, 'wslot' sets bits 9 and 15 of the first
  2669                              <1> 	; word of the I/O queue entry (write bit, inhibit bit).
  2670                              <1> 	;
  2671                              <1> 	; INPUTS ->
  2672                              <1>  	;    r1 - block number
  2673                              <1> 	;    cdev - current (block/disk) device number
  2674                              <1>  	;
  2675                              <1> 	; OUTPUTS ->
  2676                              <1> 	;    bufp - bits 9 and 15 are set, 
  2677                              <1> 	;           the remainder of the word left unchanged
  2678                              <1> 	;    r5 - points to first data word in I/O buffer
  2679                              <1> 	;
  2680                              <1> 	; ((AX = R1)) input/output
  2681                              <1> 	; ((BX = R5)) output 
  2682                              <1> 	;
  2683                              <1>         ; ((Modified registers: eDX, eCX, eBX, eSI, eDI, eBP)) 
  2684                              <1> 
  2685 00005CE8 E8DF000000          <1> 	call	bufaloc
  2686                              <1> 	; 10/07/2015
  2687                              <1> 		; jsr r0,bufaloc / get a free I/O buffer; pointer to first
  2688                              <1>         	; br 1f / word in buffer in r5
  2689                              <1> 	; eBX = Buffer (Header) Address (r5) (ES=CS=DS, system/kernel segment)
  2690                              <1>         ; eAX = Block/Sector number (r1)
  2691                              <1> wslot_0: ;1:
  2692 00005CED 66F7030024          <1>      	test	word [ebx], 2400h
  2693                              <1> 		; bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
  2694                              <1> 				; / of I/O queue entry
  2695 00005CF2 7407                <1> 	jz	short wslot_1
  2696                              <1>                 ; beq 1f  / branch if 10, 13 zero (i.e., not reading, 
  2697                              <1> 		     ; / or not waiting to read)
  2698                              <1> 
  2699                              <1>         ;; mov     ecx, [s.wait_] ; 29/07/2013
  2700 00005CF4 E833F2FFFF          <1> 	call	idle
  2701                              <1> 		; jsr r0,idle; / if buffer is reading or writing to read,
  2702                              <1>        	                     ; / idle
  2703 00005CF9 EBF2                <1> 	jmp	short wslot_0
  2704                              <1> 		; br 1b / till finished
  2705                              <1> wslot_1: ;1:
  2706 00005CFB 66810B0082          <1>         or      word [ebx], 8200h
  2707                              <1>        		; bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
  2708                              <1>                             	 ; / (write, inhibit bits)
  2709                              <1>        		; clr     *$ps / clear processor status
  2710 00005D00 83C308              <1>         add	ebx, 8 ; 11/06/2015
  2711                              <1> 		; add $8,r5 / r5 points to first word in data area 
  2712                              <1> 			  ; / for this block
  2713                              <1> dskwr_1:	; 08/02/2022
  2714 00005D03 C3                  <1>        	retn
  2715                              <1> 		; rts r0
  2716                              <1> dskwr:
  2717                              <1> 	; 08/02/2022 (Retro UNIX 386 v1.1)
  2718                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2719                              <1> 	; 14/03/2013 - 03/08/2013 (Retro UNIX 8086 v1)
  2720                              <1> 	;
  2721                              <1> 	; 'dskwr' writes a block out on disk, via ppoke. The only
  2722                              <1> 	; thing dskwr does is clear bit 15 in the first word of I/O queue
  2723                              <1> 	; entry pointed by 'bufp'. 'wslot' which must have been called
  2724                              <1> 	; previously has supplied all the information required in the
  2725                              <1> 	; I/O queue entry.
  2726                              <1> 	;
  2727                              <1> 	; (Modified registers: eCX, eDX, eBX, eSI, eDI)
  2728                              <1> 	;
  2729                              <1> 	;
  2730 00005D04 8B1D[5C6E0000]      <1> 	mov	ebx, [bufp]
  2731 00005D0A 668123FF7F          <1> 	and	word [ebx], 7FFFh ; 0111111111111111b
  2732                              <1> 		; bic $100000,*bufp / clear bit 15 of I/O queue entry at
  2733                              <1>                                   ; / bottom of queue
  2734 00005D0F E823000000          <1> 	call	poke
  2735                              <1> 	; 09/06/2015
  2736 00005D14 73ED                <1> 	jnc	short dskwr_1
  2737                              <1> 	; 08/02/2022
  2738 00005D16 803D[006F0000]FF    <1> 	cmp	byte [u.brwdev], 0FFh ; is error code set in [u.error] ?
  2739 00005D1D 7509                <1> 	jne	short dskwr_0 ; no
  2740                              <1> 	; yes, clear [u.brwdev] for next check and jump to 'error'
  2741 00005D1F C605[006F0000]00    <1> 	mov	byte [u.brwdev], 0
  2742 00005D26 EB0A                <1> 	jmp	short dskwr_2
  2743                              <1> dskwr_0:
  2744 00005D28 C705[ED6E0000]1200- <1> 	mov	dword [u.error], ERR_DRV_WRITE ; disk write error !
  2744 00005D30 0000                <1>
  2745                              <1> dskwr_2:
  2746 00005D32 E99BDDFFFF          <1> 	jmp	error
  2747                              <1> ;dskwr_1:
  2748                              <1> ;	retn
  2749                              <1> 
  2750                              <1> ;ppoke:
  2751                              <1>        		; mov $340,*$ps
  2752                              <1>        		; jsr r0,poke
  2753                              <1>        		; clr *$ps
  2754                              <1> 		; rts r0
  2755                              <1> poke:
  2756                              <1> 	; 24/12/2021 (32 bit reg push-pop)
  2757                              <1> 	; 24/10/2015
  2758                              <1> 	; 20/08/2015
  2759                              <1> 	; 18/08/2015
  2760                              <1> 	; 02/07/2015
  2761                              <1> 	; 09/06/2015 (Retro UNIX 386 v1 - Beginning)
  2762                              <1> 	; 15/03/2013 - 18/01/2014 (Retro UNIX 8086 v1)
  2763                              <1> 	;
  2764                              <1> 	; (NOTE: There are some disk I/O code modifications & extensions
  2765                              <1> 	; & exclusions on original 'poke' & other device I/O procedures of 
  2766                              <1> 	; UNIX v1 OS for performing disk I/O functions by using IBM PC 
  2767                              <1> 	; compatible rombios calls in Retro UNIX 8086 v1 kernel.)
  2768                              <1> 	;
  2769                              <1> 	; Basic I/O functions for all block structured devices
  2770                              <1> 	;
  2771                              <1>         ; (Modified registers: eCX, eDX, eSI, eDI)
  2772                              <1> 	;
  2773                              <1> 	; 20/07/2013 modifications
  2774                              <1> 	;            (Retro UNIX 8086 v1 features only !)
  2775                              <1> 	; INPUTS -> 
  2776                              <1> 	;        (EBX = buffer header address)
  2777                              <1> 	; OUTPUTS ->
  2778                              <1> 	;	 cf=0 -> successed r/w (at least, for the caller's buffer) 
  2779                              <1> 	;	 cf=1 -> error, word [eBX] = 0FFFFh
  2780                              <1> 	;		(drive not ready or r/w error!)
  2781                              <1> 	;	 (dword [EBX+4] <> 0FFFFFFFFh indicates r/w success)	
  2782                              <1> 	;	 (dword [EBx+4] = 0FFFFFFFFh means RW/IO error)
  2783                              <1> 	;        (also it indicates invalid buffer data)
  2784                              <1> 	;
  2785 00005D37 53                  <1> 	push	ebx
  2786                              <1>        		; mov r1,-(sp)
  2787                              <1>        		; mov r2,-(sp)
  2788                              <1>        		; mov r3,-(sp)
  2789 00005D38 50                  <1> 	push 	eax ; Physical Block Number (r1) (mget)
  2790                              <1> 	;
  2791                              <1> 	; 09/06/2015
  2792                              <1> 	; (permit read/write after a disk  R/W error)
  2793 00005D39 8A0B                <1> 	mov	cl, [ebx] ; device id (0 to 5)
  2794 00005D3B B001                <1> 	mov	al, 1
  2795 00005D3D D2E0                <1> 	shl	al, cl
  2796 00005D3F 8405[826E0000]      <1> 	test 	al, [active] ; busy ? (error)
  2797 00005D45 7408                <1> 	jz	short poke_0
  2798 00005D47 F6D0                <1> 	not	al
  2799 00005D49 2005[826E0000]      <1> 	and	[active], al ; reset busy bit for this device only
  2800                              <1> poke_0:
  2801 00005D4F BE[7C6E0000]        <1>         mov     esi, bufp + (4*(nbuf+2)) 
  2802                              <1> 		; mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority
  2803                              <1> 					 ; / I/O queue pointer
  2804                              <1> poke_1: ; 1:
  2805 00005D54 83EE04              <1>         sub	esi, 4
  2806 00005D57 8B1E                <1> 	mov	ebx, [esi]
  2807                              <1> 		; mov -(r2),r1 / r1 points to an I/O queue entry
  2808 00005D59 668B03              <1> 	mov	ax, [ebx] ; 17/07/2013
  2809 00005D5C F6C406              <1>        	test	ah, 06h
  2810                              <1> 	;test	word [ebx], 600h ; 0000011000000000b
  2811                              <1> 		; bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O 
  2812                              <1> 			       ; / queue entry
  2813 00005D5F 745C                <1>         jz      short poke_5
  2814                              <1> 		; beq 2f / branch to 2f if both are clear
  2815                              <1> 	; 31/07/2013
  2816                              <1> 	;test	ah, 0B0h ; (*)
  2817                              <1> 	;;test	word [ebx], 0B000h ; 1011000000000000b
  2818                              <1> 		; bit $130000,(r1) / test bits 12, 13, and 15
  2819                              <1>         ;jnz	short poke_5 ; 31/07/2013 (*)
  2820                              <1> 		; bne 2f / branch if any are set
  2821                              <1> 	;movzx	ecx, byte [ebx] ; 09/06/2015 ; Device Id
  2822                              <1>     		; movb (r1),r3 / get device id
  2823 00005D61 0FB6C8              <1> 	movzx	ecx, al ; 18/08/2015
  2824                              <1> 	;mov	edi, ecx ; 26/04/2013
  2825 00005D64 31C0                <1> 	xor 	eax, eax ; 0
  2826                              <1> 	;cmp 	[edi+drv.error], al ; 0
  2827                              <1> 		; tstb deverr(r3) / test for errors on this device
  2828                              <1>        	;jna	short poke_2 
  2829                              <1> 		; beq 3f / branch if no errors
  2830                              <1> 	; 02/07/2015
  2831                              <1> 	;dec	eax
  2832                              <1> 	;mov	[ebx+4], ax ; 0FFFFFFFFh ; -1 
  2833                              <1>        		; mov $-1,2(r1) / destroy associativity
  2834                              <1> 	;shr	eax, 24
  2835                              <1> 	;mov	[ebx], eax ; 000000FFh, reset
  2836                              <1> 		; clrb 1(r1) / do not do I/O
  2837                              <1> 	;jmp	short poke_5
  2838                              <1>         ;       ; br 2f
  2839                              <1>                 ; rts r0
  2840                              <1> poke_2: ; 3:
  2841                              <1> 	; 02/07/2015
  2842 00005D66 FEC1                <1> 	inc	cl ; 0FFh -> 0
  2843 00005D68 7453                <1> 	jz	short poke_5
  2844 00005D6A FEC0                <1> 	inc	al ; mov ax, 1
  2845 00005D6C FEC9                <1> 	dec	cl
  2846 00005D6E 7402                <1> 	jz	short poke_3
  2847                              <1> 	; 26/04/2013 Modification
  2848                              <1> 	;inc	al ; mov ax, 1
  2849                              <1> 	;or	cl, cl ; Retro UNIX 8086 v1 device id.
  2850                              <1> 	;jz	short poke_3 ; cl = 0
  2851 00005D70 D2E0                <1> 	shl	al, cl ; shl ax, cl
  2852                              <1> poke_3:
  2853                              <1> 	;test	[active], ax
  2854 00005D72 8405[826E0000]      <1> 	test	[active], al
  2855                              <1> 		; bit $2,active / test disk busy bit
  2856 00005D78 7543                <1> 	jnz     short poke_5
  2857                              <1> 		; bne 2f / branch if bit is set
  2858                              <1> 	;or	[active], ax
  2859 00005D7A 0805[826E0000]      <1> 	or	[active], al
  2860                              <1> 		; bis $2,active / set disk busy bit
  2861                              <1> 	;push	ax
  2862                              <1> 	; 24/12/2021
  2863 00005D80 50                  <1> 	push	eax
  2864 00005D81 E8C9000000          <1> 	call	diskio ; Retro UNIX 8086 v1 Only !
  2865                              <1> 	;mov    [edi+drv.error], ah
  2866                              <1> 	; 24/12/2021
  2867 00005D86 58                  <1> 	pop	eax
  2868                              <1> 	;pop	ax
  2869 00005D87 730E                <1> 	jnc	short poke_4 ; 20/07/2013
  2870                              <1> 	;cmp 	[edi+drv.error], al ; 0	
  2871                              <1> 	;jna	short poke_4
  2872                              <1> 		; tstb deverr(r3) / test for errors on this device
  2873                              <1>        		; beq 3f / branch if no errors
  2874                              <1> 	; 02/07/2015 (32 bit modification)
  2875                              <1> 	; 20/07/2013
  2876 00005D89 C74304FFFFFFFF      <1> 	mov	dword [ebx+4], 0FFFFFFFFh ; -1 
  2877                              <1>        		; mov $-1,2(r1) / destroy associativity
  2878 00005D90 66C703FF00          <1> 	mov	word [ebx], 0FFh ; 20/08/2015 
  2879                              <1> 		; clrb 1(r1) / do not do I/O
  2880 00005D95 EB26                <1> 	jmp     short poke_5
  2881                              <1> poke_4:	; 20/07/2013
  2882                              <1> 	; 17/07/2013
  2883 00005D97 F6D0                <1> 	not 	al 
  2884 00005D99 2005[826E0000]      <1> 	and	[active], al ; reset, not busy
  2885                              <1> 	; eBX = system I/O buffer header (queue entry) address
  2886                              <1> seta: ; / I/O queue bookkeeping; set read/write waiting bits.
  2887 00005D9F 668B03              <1> 	mov	ax, [ebx]
  2888                              <1>        		; mov (r1),r3 / move word 1 of I/O queue entry into r3
  2889 00005DA2 66250006            <1>         and	ax, 600h
  2890                              <1> 		; bic $!3000,r3 / clear all bits except 9 and 10
  2891 00005DA6 668123FFF9          <1> 	and 	word [ebx], 0F9FFh
  2892                              <1>        		; bic $3000,(r1) / clear only bits 9 and 10
  2893 00005DAB C0E403              <1> 	shl	ah, 3
  2894                              <1>        		; rol r3
  2895                              <1>                 ; rol r3
  2896                              <1>                 ; rol r3	
  2897 00005DAE 660903              <1> 	or	[ebx], ax
  2898                              <1> 		; bis r3,(r1) / or old value of bits 9 and 10 with 
  2899                              <1> 			   ; bits 12 and 13
  2900 00005DB1 E876F1FFFF          <1> 	call	idle ; 18/01/2014
  2901                              <1> 	;; sti
  2902                              <1> 	;hlt 	; wait for a hardware interrupt
  2903                              <1> 	;; cli
  2904                              <1> 	; NOTE: In fact, disk controller's 'disk I/O completed' 
  2905                              <1>         ; interrupt would be used to reset busy bits, but INT 13h
  2906                              <1> 	; returns when disk I/O is completed. So, here, as temporary
  2907                              <1> 	; method, this procedure will wait for a time according to
  2908                              <1> 	; multi tasking and time sharing concept.
  2909                              <1> 	;
  2910                              <1> 	; 24/10/2015
  2911                              <1> 	;not	ax 
  2912 00005DB6 66B8FF00            <1> 	mov 	ax, 0FFh ; 24/10/2015 (temporary)
  2913 00005DBA 662103              <1> 	and	[ebx], ax ; clear bits 12 and 13
  2914                              <1> poke_5: ;2:
  2915 00005DBD 81FE[5C6E0000]      <1>         cmp     esi, bufp
  2916                              <1>                ; cmp r2,$bufp / test to see if entire I/O queue 
  2917                              <1>                             ; / has been scanned
  2918 00005DC3 778F                <1> 	ja      short poke_1
  2919                              <1>                ; bhi 1b
  2920                              <1> 	; 24/03/2013
  2921                              <1>        		; mov (sp)+,r3
  2922                              <1>        		; mov (sp)+,r2
  2923                              <1>        		; mov (sp)+,r1
  2924 00005DC5 58                  <1>         pop 	eax  ; Physical Block Number (r1) (mget)
  2925 00005DC6 5B                  <1> 	pop 	ebx
  2926                              <1> 	; 02/07/2015 (32 bit modification)
  2927                              <1> 	; 20/07/2013
  2928                              <1> 	;cmp 	dword [ebx+4], 0FFFFFFFFh
  2929 00005DC7 803BFF              <1> 	cmp	byte [ebx], 0FFh ; 20/08/2015
  2930                              <1> 	;	
  2931                              <1> 	; 'poke' returns with cf=0 if the requested buffer is read 
  2932                              <1> 	; or written successfully; even if an error occurs while
  2933                              <1> 	; reading to or writing from other buffers. 20/07/2013
  2934                              <1> 	;
  2935                              <1> 	; 09/06/2015
  2936 00005DCA F5                  <1> 	cmc
  2937 00005DCB C3                  <1> 	retn
  2938                              <1>                 ; rts r0
  2939                              <1> 
  2940                              <1> bufaloc:
  2941                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2942                              <1> 	; 20/08/2015
  2943                              <1> 	; 19/08/2015
  2944                              <1> 	; 02/07/2015
  2945                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  2946                              <1> 	;	     (32 bit modifications)	
  2947                              <1> 	; 13/03/2013 - 29/07/2013 (Retro UNIX 8086 v1)
  2948                              <1> 	;
  2949                              <1> 	; bufaloc - Block device I/O buffer allocation
  2950                              <1> 	; 
  2951                              <1> 	; INPUTS ->
  2952                              <1> 	;    r1 - block number
  2953                              <1> 	;    cdev - current (block/disk) device number
  2954                              <1> 	;    bufp+(2*n)-2 --- n = 1 ... nbuff
  2955                              <1> 	; OUTPUTS ->
  2956                              <1> 	;    r5 - pointer to buffer allocated
  2957                              <1> 	;    bufp ... bufp+12 --- (bufp), (bufp)+2
  2958                              <1> 	;
  2959                              <1> 	; ((AX = R1)) input/output
  2960                              <1> 	; ((BX = R5)) output
  2961                              <1>         ;    ((Modified registers: DX, CX, BX, SI, DI, BP))
  2962                              <1> 	;    zf=1 -> block already in a I/O buffer
  2963                              <1> 	;    zf=0 -> a new I/O buffer has been allocated
  2964                              <1> 	;    ((DL = Device ID))
  2965                              <1> 	;    (((DH = 0 or 1)))
  2966                              <1> 	;    (((CX = previous value of word ptr [bufp])))
  2967                              <1> 	;    ((CX and DH will not be used after return)))
  2968                              <1> 
  2969                              <1> 	;;push 	esi ; ***
  2970                              <1> 		; mov r2,-(sp) / save r2 on stack
  2971                              <1>        		; mov $340,*$ps / set processor priority to 7
  2972                              <1> 	; 20/07/2013
  2973                              <1> 	; 26/04/2013
  2974                              <1> 	;movzx	ebx, byte [cdev] ; 0 or 1
  2975                              <1> 	;mov	edi, rdev ; offset mdev = offset rdev + 1
  2976                              <1> 	;add	edi, ebx
  2977                              <1> 	; 09/01/2022
  2978 00005DCC 0FB63D[7F6E0000]    <1> 	movzx	edi, byte [cdev] ; 0 or 1
  2979 00005DD3 81C7[806E0000]      <1> 	add	edi, rdev
  2980                              <1> bufaloc_0: ; 26/04/2013 !! here is called from bread or bwrite !!
  2981                              <1> 			;; eDI points to device id.
  2982 00005DD9 0FB61F              <1> 	movzx	ebx, byte [edi] ; [EDI] -> rdev/mdev or brwdev
  2983                              <1> 	; 11/06/2015
  2984 00005DDC 80BB[1A660000]F0    <1> 	cmp 	byte [ebx+drv.status], 0F0h ; Drive not ready !
  2985 00005DE3 720F                <1> 	jb	short bufaloc_9
  2986 00005DE5 C705[ED6E0000]0F00- <1> 	mov	dword [u.error], ERR_DRV_NOT_RDY
  2986 00005DED 0000                <1>
  2987 00005DEF E9DEDCFFFF          <1> 	jmp	error
  2988                              <1> bufaloc_9:
  2989 00005DF4 89DA                <1> 	mov	edx, ebx ; dh = 0, dl = device number (0 to 5)
  2990                              <1> bufaloc_10: ; 02/07/2015
  2991 00005DF6 31ED                <1> 	xor 	ebp, ebp ; 0
  2992 00005DF8 55                  <1> 	push	ebp ; 0
  2993 00005DF9 89E5                <1>         mov     ebp, esp	
  2994                              <1> 	;
  2995                              <1> bufaloc_1: ;1:
  2996                              <1> 		; clr -(sp) / vacant buffer
  2997 00005DFB BE[5C6E0000]        <1>         mov 	esi, bufp
  2998                              <1> 		; mov $bufp,r2 / bufp contains pointers to I/O queue 
  2999                              <1> 			     ; / entrys in buffer area
  3000                              <1> bufaloc_2: ;2:
  3001 00005E00 8B1E                <1> 	mov	ebx, [esi]
  3002                              <1>        		; mov (r2)+,r5 / move pointer to word 1 of an I/O 
  3003                              <1> 			    ; queue entry into r5
  3004 00005E02 66F70300F6          <1> 	test	word [ebx], 0F600h
  3005                              <1> 		; bit $173000,(r5) / lock+keep+active+outstanding
  3006 00005E07 7503                <1>         jnz	short bufaloc_3
  3007                              <1> 		; bne 3f / branch when 
  3008                              <1> 		       ; / any of bits 9,10,12,13,14,15 are set
  3009                              <1>                        ; / (i.e., buffer busy)
  3010 00005E09 897500              <1>         mov     [ebp], esi ; pointer to I/0 queue entry
  3011                              <1>                 ; mov  r2,(sp) ;/ save pointer to last non-busy buffer
  3012                              <1> 			; / found points to word 2 of I/O queue entry)
  3013                              <1> bufaloc_3: ;3:
  3014                              <1> 	;mov	dl, [edi] ; 26/04/2013
  3015                              <1> 	;
  3016 00005E0C 3813                <1> 	cmp	[ebx], dl	
  3017                              <1> 		; cmpb (r5),cdev / is device in I/O queue entry same 
  3018                              <1> 			       ; / as current device
  3019 00005E0E 7508                <1> 	jne	short bufaloc_4
  3020                              <1>        		; bne 3f
  3021 00005E10 394304              <1> 	cmp	[ebx+4], eax
  3022                              <1>        		; cmp 2(r5),r1 / is block number in I/O queue entry, 
  3023                              <1> 			     ; / same as current block number
  3024 00005E13 7503                <1>        	jne	short bufaloc_4
  3025                              <1> 		; bne 3f
  3026                              <1> 	;add	esp, 4
  3027 00005E15 59                  <1> 	pop	ecx
  3028                              <1>        		; tst (sp)+ / bump stack pointer
  3029 00005E16 EB20                <1> 	jmp	short bufaloc_7 ; Retro Unix 8086 v1 modification
  3030                              <1> 				; jump to bufaloc_6 in original Unix v1
  3031                              <1>        		; br 1f / use this buffer
  3032                              <1> bufaloc_4: ;3:
  3033 00005E18 83C604              <1> 	add	esi, 4 ; 20/08/2015
  3034                              <1> 	;
  3035 00005E1B 81FE[746E0000]      <1> 	cmp	esi, bufp + (nbuf*4)
  3036                              <1> 		; cmp r2,$bufp+nbuf+nbuf
  3037 00005E21 72DD                <1> 	jb	short bufaloc_2
  3038                              <1> 		; blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
  3039                              <1>                        ; / buffers not checked)
  3040 00005E23 5E                  <1>         pop	esi
  3041                              <1> 		; mov (sp)+,r2 / once all bufs are examined move pointer
  3042                              <1> 			     ; / to last free block
  3043 00005E24 09F6                <1>        	or	esi, esi 
  3044 00005E26 7507                <1> 	jnz	short bufaloc_5
  3045                              <1> 		; bne 2f / if (sp) is non zero, i.e., 
  3046                              <1> 	        ; / if a free buffer is found branch to 2f
  3047                              <1>         ;; mov  ecx, [s.wait_]
  3048 00005E28 E8FFF0FFFF          <1> 	call	idle
  3049                              <1> 		; jsr r0,idle; s.wait+2 / idle if no free buffers
  3050 00005E2D EBC7                <1> 	jmp 	short bufaloc_10 ; 02/07/2015
  3051                              <1>        		; br 1b
  3052                              <1> bufaloc_5: ;2:
  3053                              <1> 		; tst (r0)+ / skip if warmed over buffer
  3054 00005E2F FEC6                <1> 	inc	dh ; Retro UNIX 8086 v1 modification
  3055                              <1> bufaloc_6: ;1:
  3056 00005E31 8B1E                <1>         mov    	ebx, [esi] 
  3057                              <1> 		; mov -(r2),r5 / put pointer to word 1 of I/O queue 
  3058                              <1> 			     ; / entry in r5
  3059                              <1> 	;; 26/04/2013
  3060                              <1>         ;mov	dl, [edi] ; byte [rdev] or byte [mdev]
  3061 00005E33 8813                <1> 	mov 	[ebx], dl
  3062                              <1> 		; movb cdev,(r5) / put current device number 
  3063                              <1> 				 ; / in I/O queue entry
  3064 00005E35 894304              <1> 	mov 	[ebx+4], eax
  3065                              <1> 		; mov r1,2(r5) / move block number into word 2 
  3066                              <1> 			     ; / of I/O queue entry
  3067                              <1> bufaloc_7: ;1:
  3068 00005E38 81FE[5C6E0000]      <1>         cmp	esi, bufp
  3069                              <1> 		; cmp r2,$bufp / bump all entrys in bufp 
  3070                              <1> 			     ; / and put latest assigned
  3071 00005E3E 760A                <1> 	jna	short bufaloc_8	
  3072                              <1>        		; blos 1f / buffer on the top 
  3073                              <1> 			; / (this makes if the lowest priority)
  3074 00005E40 83EE04              <1> 	sub	esi, 4
  3075 00005E43 8B0E                <1> 	mov	ecx, [esi]
  3076 00005E45 894E04              <1> 	mov	[esi+4], ecx
  3077                              <1> 		; mov -(r2),2(r2) / job for a particular device
  3078 00005E48 EBEE                <1> 	jmp 	short bufaloc_7        
  3079                              <1> 		; br 1b
  3080                              <1> bufaloc_8: ;1:
  3081 00005E4A 891E                <1>         mov	[esi], ebx
  3082                              <1> 		; mov r5,(r2)
  3083                              <1> 	;;pop	esi ; ***
  3084                              <1>        		; mov (sp)+,r2 / restore r2
  3085 00005E4C 08F6                <1>        	or 	dh, dh ; 0 or 1 ?
  3086                              <1> 		; Retro UNIX 8086 v1 modification
  3087                              <1> 		; zf=1 --> block already is in an I/O buffer
  3088                              <1> 		; zf=0 --> a new I/O buffer has been allocated
  3089 00005E4E C3                  <1> 	retn
  3090                              <1> 		; rts r0
  3091                              <1> 
  3092                              <1> diskio:
  3093                              <1> 	; 12/02/2022
  3094                              <1> 	; 10/02/2022
  3095                              <1> 	; 08/02/2022
  3096                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1 2022, Kernel v0.2.1.2)
  3097                              <1> 	; 10/07/2015
  3098                              <1> 	; 02/07/2015
  3099                              <1> 	; 16/06/2015
  3100                              <1> 	; 11/06/2015 (Retro UNIX 386 v1 - Beginning)
  3101                              <1> 	;	     (80386 protected mode modifications)	
  3102                              <1> 	; 15/03/2013 - 29/04/2013 (Retro UNIX 8086 v1)
  3103                              <1> 	;
  3104                              <1> 	; Retro UNIX 8086 v1 feature only !
  3105                              <1> 	;
  3106                              <1> 	; Derived from proc_chs_read procedure of TRDOS DISKIO.ASM (2011)
  3107                              <1> 	; 04/07/2009 - 20/07/2011
  3108                              <1> 	;
  3109                              <1> 	; NOTE: Reads only 1 block/sector (sector/block size is 512 bytes)
  3110                              <1> 	;
  3111                              <1>         ; INPUTS ->
  3112                              <1> 	; 	   eBX = System I/O Buffer header address
  3113                              <1> 	;
  3114                              <1>         ; OUTPUTS -> cf=0 --> done 
  3115                              <1> 	; 	     cf=1 --> error code in AH
  3116                              <1> 	;	     ; 08/02/2022
  3117                              <1> 	;	     cf=1 & [u.brwdev] = 0FFh -->
  3118                              <1> 	;		error code in [u.error]
  3119                              <1> 	;		
  3120                              <1> 	; (Modified registers: eAX, eCX, eDX)
  3121                              <1> 	
  3122                              <1> ;rw_disk_sector:
  3123                              <1> 	; 12/02/2022
  3124                              <1> 	; 10/02/2022
  3125                              <1> 	; 08/02/2022
  3126                              <1> 	; 10/07/2015
  3127                              <1> 	; 02/07/2015
  3128                              <1> 	; 11/06/2015 - Retro UNIX 386 v1 - 'u8.s' 
  3129                              <1> 	; 21/02/2015 ('dsectpm.s', 'read_disk_sector')
  3130                              <1> 	; 16/02/2015 (Retro UNIX 386 v1 test - 'unix386.s')
  3131                              <1> 	; 01/12/2014 - 18/01/2015 ('dsectrm2.s')
  3132                              <1> 	;
  3133                              <1> 	;mov	dx, 0201h ; Read 1 sector/block
  3134 00005E4F B602                <1> 	mov	dh, 2
  3135 00005E51 668B03              <1> 	mov	ax, [ebx] 
  3136                              <1> 	;
  3137 00005E54 56                  <1> 	push	esi ; ****
  3138 00005E55 53                  <1> 	push	ebx ; ***
  3139                              <1> 	;
  3140 00005E56 0FB6C8              <1> 	movzx	ecx, al
  3141 00005E59 89CE                <1> 	mov	esi, ecx
  3142                              <1> 	;
  3143 00005E5B 38F1                <1> 	cmp	cl, dh ; 2
  3144 00005E5D 7202                <1> 	jb	short rwdsk0
  3145 00005E5F 047E                <1> 	add	al, 7Eh  ; 80h, 81h, 82h, 83h
  3146                              <1> rwdsk0:
  3147 00005E61 A2[CB650000]        <1> 	mov	[drv], al
  3148 00005E66 81C6[1A660000]      <1> 	add	esi, drv.status
  3149                              <1> 	; 11/06/2015
  3150 00005E6C 803EF0              <1> 	cmp	byte [esi], 0F0h 
  3151 00005E6F 7204                <1> 	jb      short rwdsk1
  3152                              <1> 	; 'drive not ready' error
  3153                              <1> 	; 10/02/2022
  3154                              <1> 	; 08/02/2022
  3155                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3156                              <1> 	;mov	dword [u.error], ERR_DRV_NOT_RDY
  3157                              <1> 	;;jmp	error
  3158                              <1> 	;stc	; cf = 1
  3159                              <1> 	;retn
  3160                              <1> 	; 10/02/2022
  3161 00005E71 B10F                <1> 	mov	cl, ERR_DRV_NOT_RDY
  3162 00005E73 EB20                <1> 	jmp	short rwdsk_err1
  3163                              <1> rwdsk1:
  3164 00005E75 F6C402              <1> 	test	ah, 2
  3165                              <1> 	;test	ax, 200h ; Bit 9 of word 0 (status word)
  3166                              <1> 			 ; write bit
  3167 00005E78 7402                <1> 	jz	short rwdsk2
  3168                              <1> 	;test	ah, 4
  3169                              <1> 	;;test	ax, 400h ; Bit 10 of word 0 (status word)
  3170                              <1> 	;		 ; read bit
  3171                              <1> 	;jz	short diskio_ret
  3172 00005E7A FEC6                <1> 	inc	dh ; 03h = write
  3173                              <1> rwdsk2:
  3174 00005E7C 88C2                <1> 	mov	dl, al
  3175 00005E7E 83C304              <1> 	add	ebx, 4 ; sector/block address/number pointer
  3176 00005E81 8B03                <1> 	mov	eax, [ebx] ; sector/block number (LBA)
  3177 00005E83 C0E102              <1> 	shl	cl, 2
  3178 00005E86 81C1[FE650000]      <1> 	add	ecx, drv.size ; disk size
  3179 00005E8C 3B01                <1> 	cmp	eax, [ecx] ; Last sector + 1 (number of secs.)
  3180 00005E8E 7214                <1> 	jb      short rwdsk3
  3181                              <1>  	; 'out of volume' error
  3182                              <1> 	; 10/02/2022
  3183                              <1> 	; 08/02/2022
  3184                              <1> 	;mov	byte [u.brwdev], 0FFh ; error code in [u.error]
  3185                              <1> 	;mov 	dword [u.error], ERR_DEV_VOL_SIZE
  3186                              <1> 	;;jmp	error
  3187                              <1> 	;stc	; cf = 1
  3188                              <1> 	;retn
  3189                              <1> 	; 10/02/2022
  3190 00005E90 B910000000          <1> 	mov	ecx, ERR_DEV_VOL_SIZE
  3191                              <1> rwdsk_err1:
  3192 00005E95 C605[006F0000]FF    <1> 	mov	byte [u.brwdev], 0FFh
  3193 00005E9C 890D[ED6E0000]      <1> 	mov 	[u.error], ecx ; 12/02/2022
  3194 00005EA2 EB30                <1> 	jmp	short rwdsk_err2
  3195                              <1> rwdsk3:
  3196                              <1> 	; 11/06/2015
  3197 00005EA4 83C304              <1> 	add	ebx, 4 ; buffer address
  3198 00005EA7 C605[1E6F0000]04    <1> 	mov	byte [retry_count], 4
  3199 00005EAE F60601              <1> 	test	byte [esi], 1 ; LBA ready ?
  3200 00005EB1 7432                <1>         jz      short rwdsk_chs
  3201                              <1> rwdsk_lba:
  3202                              <1> 	; LBA read/write (with private LBA function) 
  3203                              <1> 	;((Retro UNIX 386 v1 - DISK I/O code by Erdogan Tan))
  3204 00005EB3 83C607              <1>         add     esi, drv.error - drv.status ; 10/07/2015
  3205 00005EB6 89C1                <1> 	mov	ecx, eax ; sector number
  3206                              <1> 	; ebx = buffer (data) address
  3207                              <1> 	; dl = physical drive number (0,1, 80h, 81h, 82h, 83h)
  3208                              <1> rwdsk_lba_retry:
  3209                              <1> 	;mov	dl, [drv]
  3210                              <1> 		; Function 1Bh = LBA read, 1Ch = LBA write
  3211 00005EB8 B419                <1> 	mov	ah, 1Ch - 3h ; LBA write function number - 3
  3212 00005EBA 00F4                <1> 	add	ah, dh		
  3213 00005EBC B001                <1> 	mov	al, 1
  3214                              <1> 	;int	13h
  3215 00005EBE E8D9C6FFFF          <1> 	call	int13h
  3216 00005EC3 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3217 00005EC5 730E                <1> 	jnc	short rwdsk_lba_ok
  3218 00005EC7 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3219 00005ECA 7408                <1>         je      short rwdsk_lba_fails
  3220 00005ECC FE0D[1E6F0000]      <1> 	dec	byte [retry_count]
  3221 00005ED2 7504                <1>         jnz     short rwdsk_lba_reset ; 10/07/2015
  3222                              <1> rwdsk_err2:	; 10/02/2022
  3223                              <1> rwdsk_lba_fails:
  3224 00005ED4 F9                  <1> 	stc
  3225                              <1> rwdsk_lba_ok:
  3226 00005ED5 5B                  <1> 	pop	ebx ; ***
  3227 00005ED6 5E                  <1> 	pop	esi ; ****
  3228 00005ED7 C3                  <1> 	retn
  3229                              <1> rwdsk_lba_reset:
  3230 00005ED8 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3231                              <1> 	;int	13h
  3232 00005EDA E8BDC6FFFF          <1>         call	int13h
  3233 00005EDF 73D7                <1> 	jnc     short rwdsk_lba_retry
  3234 00005EE1 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3235 00005EE3 EBF0                <1> 	jmp	short rwdsk_lba_ok
  3236                              <1> 	;
  3237                              <1> 	; CHS read (convert LBA address to CHS values)	
  3238                              <1> rwdsk_chs:
  3239                              <1> 	; 10/07/2015
  3240 00005EE5 81EE[1A660000]      <1> 	sub	esi, drv.status
  3241 00005EEB 89F1                <1> 	mov	ecx, esi
  3242 00005EED 81C6[21660000]      <1> 	add 	esi, drv.error
  3243                              <1> 	; 02/07/2015
  3244                              <1> 	; 16/06/2015
  3245                              <1>  	; 11/06/2015 
  3246 00005EF3 53                  <1> 	push	ebx ; ** ; buffer
  3247 00005EF4 D1E1                <1> 	shl	ecx, 1
  3248 00005EF6 51                  <1> 	push	ecx ; * 
  3249                              <1> 	;
  3250 00005EF7 89CB                <1> 	mov	ebx, ecx
  3251 00005EF9 8835[1D6F0000]      <1> 	mov	[rwdsk], dh ; 02/07/2015
  3252 00005EFF 31D2                <1> 	xor	edx, edx ; 0
  3253                              <1> 	; 09/01/2022
  3254                              <1> 	;sub	ecx, ecx 
  3255 00005F01 81C3[F0650000]      <1>         add     ebx, drv.spt
  3256 00005F07 668B0B              <1> 	mov	cx, [ebx] ; sector per track
  3257                              <1> 		; EDX:EAX = LBA
  3258 00005F0A F7F1                <1> 	div	ecx
  3259 00005F0C 88D1                <1> 	mov	cl, dl	; sector number - 1
  3260 00005F0E FEC1                <1> 	inc	cl	; sector number (1 based)
  3261 00005F10 5B                  <1> 	pop	ebx ; * ; 11/06/2015
  3262                              <1> 	;push	cx
  3263                              <1>         ; 09/01/2022
  3264 00005F11 51                  <1> 	push	ecx
  3265 00005F12 81C3[E2650000]      <1> 	add     ebx, drv.heads
  3266 00005F18 668B0B              <1> 	mov	cx, [ebx] ; heads
  3267 00005F1B 31D2                <1> 	xor	edx, edx
  3268                              <1> 		; EAX = cylinders * heads + head
  3269 00005F1D F7F1                <1> 	div	ecx
  3270                              <1> 	;pop	cx     ; sector number
  3271                              <1> 	; 09/01/2022
  3272 00005F1F 59                  <1> 	pop	ecx
  3273 00005F20 88D6                <1> 	mov	dh, dl ; head number
  3274 00005F22 8A15[CB650000]      <1> 	mov	dl, [drv]
  3275 00005F28 88C5                <1> 	mov	ch, al ; cylinder (bits 0-7)
  3276 00005F2A C0E406              <1> 	shl	ah, 6
  3277 00005F2D 08E1                <1> 	or	cl, ah ; cylinder (bits 8-9)
  3278                              <1> 		       ; sector (bits 0-7)
  3279 00005F2F 5B                  <1> 	pop	ebx ; ** ; buffer ; 11/06/2015
  3280                              <1> 		; CL = sector (bits 0-5)
  3281                              <1> 		;      cylinder (bits 8-9 -> bits 6-7)
  3282                              <1> 		; CH = cylinder (bits 0-7)
  3283                              <1> 		; DH = head
  3284                              <1> 		; DL = drive
  3285                              <1> 	;
  3286 00005F30 C605[1E6F0000]04    <1> 	mov	byte [retry_count], 4
  3287                              <1> rwdsk_retry:	
  3288 00005F37 8A25[1D6F0000]      <1> 	mov	ah, [rwdsk] ; 02h = read, 03h = write
  3289 00005F3D B001                <1> 	mov	al, 1 ; sector count	
  3290                              <1> 	;int	13h
  3291 00005F3F E858C6FFFF          <1> 	call	int13h
  3292 00005F44 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3293 00005F46 730E                <1> 	jnc	short rwdsk_ok ; ah = 0
  3294 00005F48 80FC80              <1> 	cmp	ah, 80h ; time out ?
  3295 00005F4B 7408                <1> 	je	short rwdsk_fails
  3296 00005F4D FE0D[1E6F0000]      <1> 	dec	byte [retry_count]
  3297 00005F53 7504                <1> 	jnz	short rwdsk_reset
  3298                              <1> rwdsk_fails:
  3299 00005F55 F9                  <1> 	stc
  3300                              <1> rwdsk_ok:
  3301 00005F56 5B                  <1> 	pop	ebx ; ***
  3302 00005F57 5E                  <1> 	pop	esi ; ****
  3303 00005F58 C3                  <1> 	retn
  3304                              <1> rwdsk_reset:
  3305                              <1> 	; 02/02/2015
  3306 00005F59 28E4                <1> 	sub	ah, ah
  3307 00005F5B 80FA80              <1> 	cmp	dl, 80h
  3308 00005F5E 7202                <1> 	jb	short rwdsk_fd_reset
  3309 00005F60 B40D                <1> 	mov	ah, 0Dh ; Alternate reset
  3310                              <1> rwdsk_fd_reset:
  3311                              <1> 	;int	13h
  3312 00005F62 E835C6FFFF          <1>         call	int13h
  3313 00005F67 73CE                <1> 	jnc	short rwdsk_retry
  3314 00005F69 8826                <1> 	mov	[esi], ah ; error code ; 10/07/2015
  3315 00005F6B EBE9                <1> 	jmp 	short rwdsk_ok
  3316                              <1> 
  3317                              <1> ; Original UNIX v1 - drum (& disk) interrupt routine
  3318                              <1> ;	(Equivalent to IRQ 14 & IRQ 15 disk/hardware interrupts)
  3319                              <1> ;
  3320                              <1> ; This feature is not used in Retro UNIX 386 (& 8086) for now.
  3321                              <1> ; Because, current Retro UNIX 386 disk I/O -INT13H- routine is 
  3322                              <1> ; derived from IBM PC AT -infact: XT286- BIOS source code, int 13h
  3323                              <1> ; that uses hardware -transfer has been completed-  interrupt inside it. 
  3324                              <1> ; In a next Retro UNIX 386 version, these interrupts
  3325                              <1> ; (fdc_int, hdc1_int, hdc2_int) will be handled by a separate routine
  3326                              <1> ; as in original unix v1.
  3327                              <1> ; I am not removing IBM BIOS source code derivatives -compatible code-
  3328                              <1> ; for now, regarding the new/next 32 bit TRDOS project by me
  3329                              <1> ; (to keep source code files easy adaptable to 32 bit TRDOS.)
  3330                              <1> ;
  3331                              <1> ; Erdogan tan (10/07/2015) 
  3332                              <1> 
  3333                              <1> ;drum: / interrupt handler
  3334                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3335                              <1> ;       jsr     r0,trapt; dcs; rfap; 1 / check for stray interrupt or
  3336                              <1> ;                                      / error
  3337                              <1> ;               br 3f / no, error
  3338                              <1> ;       br      2f / error
  3339                              <1> ;
  3340                              <1> ;disk:
  3341                              <1> ;       jsr     r0,setisp / save r1,r2,r3, and clockp on the stack
  3342                              <1> ;       jmp     *$0f
  3343                              <1> ;0:
  3344                              <1> ;       jsr     r0,trapt; rkcs; rkap; 2
  3345                              <1> ;      	        br 3f / no, errors
  3346                              <1> ;       mov     $115,(r2) / drive reset, errbit was set
  3347                              <1> ;       mov     $1f,0b-2 / next time jmp *$0f is executed jmp will be
  3348                              <1> ;                        / to 1f
  3349                              <1> ;       br      4f
  3350                              <1> ;1:
  3351                              <1> ;       bit     $20000,rkcs
  3352                              <1> ;       beq     4f / wait for seek complete
  3353                              <1> ;       mov     $0b,0b-2
  3354                              <1> ;       mov     rkap,r1
  3355                              <1> ;2:
  3356                              <1> ;       bit     $3000,(r1) / are bits 9 or 10 set in the 1st word of
  3357                              <1> ;                          / the disk buffer
  3358                              <1> ;       bne     3f / no, branch ignore error if outstanding
  3359                              <1> ;       inc     r1
  3360                              <1> ;       asr     (r1)
  3361                              <1> ;       asr     (r1)
  3362                              <1> ;       asr     (r1) / reissue request
  3363                              <1> ;       dec     r1
  3364                              <1> ;3:
  3365                              <1> ;       bic     $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
  3366                              <1> ;       mov     ac,-(sp)
  3367                              <1> ;       mov     mq,-(sp) / put these on the stack
  3368                              <1> ;       mov     sc,-(sp)
  3369                              <1> ;       jsr     r0,poke
  3370                              <1> ;       mov     (sp)+,sc
  3371                              <1> ;       mov     (sp)+,mq / pop them off stack
  3372                              <1> ;       mov     (sp)+,ac
  3373                              <1> ;4:
  3374                              <1> ;       jmp     retisp / u4-3
  3375                              <1> ;
  3376                              <1> ;trapt:                  / r2 points to the
  3377                              <1> ;       mov     (r0)+,r2 / device control register
  3378                              <1> ;       mov     *(r0)+,r1 / transaction pointer points to buffer
  3379                              <1> ;       tst     (sp)+
  3380                              <1> ;       tstb    (r2) / is ready bit of dcs set?
  3381                              <1> ;       bge     4b / device still active so branch
  3382                              <1> ;       bit     (r0),active / was device busy?
  3383                              <1> ;       beq     4b / no, stray interrupt
  3384                              <1> ;       bic     (r0)+,active / yes, set active to zero
  3385                              <1> ;       tst     (r2) / test the err(bit is) of dcs
  3386                              <1> ;       bge     2f / if no error jump to 2f
  3387                              <1> ;       tst     (r0)+ / skip on error
  3388                              <1> ; 2:
  3389                              <1> ;       jmp     (r0)
  2104                                  %include 'u9.s'        ; 29/06/2015
  2105                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYS9.INC
  2106                              <1> ; Last Modification: 27/02/2022
  2107                              <1> ; ----------------------------------------------------------------------------
  2108                              <1> ; Derived from 'Retro UNIX 8086 v1' source code by Erdogan Tan
  2109                              <1> ; (v0.1 - Beginning: 11/07/2012)
  2110                              <1> ;
  2111                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2112                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2113                              <1> ; <Bell Laboratories (17/3/1972)>
  2114                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2115                              <1> ;
  2116                              <1> ; Retro UNIX 8086 v1 - U9.ASM (01/09/2014) //// UNIX v1 -> u9.s
  2117                              <1> ;
  2118                              <1> ; ****************************************************************************
  2119                              <1> 
  2120                              <1> getch:
  2121                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2122                              <1> 	; 30/06/2015
  2123                              <1> 	; 18/02/2015 - Retro UNIX 386 v1 - feature only!
  2124 00005F6D 28C0                <1> 	sub	al, al ; 0
  2125                              <1> getch_q: ; 06/08/2015
  2126 00005F6F 8A25[066B0000]      <1> 	mov 	ah, [ptty] ; active (current) video page
  2127 00005F75 EB06                <1>         jmp     short getc_n
  2128                              <1> 
  2129                              <1> getc: 
  2130                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2131                              <1> 	; 12/11/2015
  2132                              <1> 	; 15/09/2015
  2133                              <1> 	; 01/07/2015
  2134                              <1> 	; 30/06/2015
  2135                              <1> 	; 18/02/2015 (Retro UNIX 386 v1 - Beginning)
  2136                              <1> 	; 13/05/2013 - 04/07/2014 (Retro UNIX 8086 v1)
  2137                              <1> 	;
  2138                              <1> 	; Retro UNIX 8086 v1 modification !
  2139                              <1> 	; 
  2140                              <1> 	; 'getc' gets (next) character 
  2141                              <1> 	;	 from requested TTY (keyboard) buffer 
  2142                              <1> 	; INPUTS ->
  2143                              <1> 	;     [u.ttyn] = tty number (0 to 7) (8 is COM1, 9 is COM2)	
  2144                              <1> 	;     AL=0 -> Get (next) character from requested TTY buffer
  2145                              <1> 	;	(Keyboard buffer will point to 
  2146                              <1> 	;			next character at next call)
  2147                              <1> 	;     AL=1 -> Test a key is available in requested TTY buffer
  2148                              <1> 	;	(Keyboard buffer will point to 
  2149                              <1> 	;			current character at next call)
  2150                              <1> 	; OUTPUTS ->
  2151                              <1> 	;     (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2152                              <1> 	;     			 ZF=0 -> AX has (current) character
  2153                              <1> 	;      AL = ascii code
  2154                              <1> 	;      AH = scan code	(AH = line status for COM1 or COM2)	 			
  2155                              <1> 	; 		        (cf=1 -> error code/flags in AH)
  2156                              <1> 	; Original UNIX V1 'getc': 
  2157                              <1> 	;		get a character off character list
  2158                              <1> 	;
  2159                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))	
  2160                              <1> 	;
  2161                              <1> 	; 30/06/2015 (32 bit modifications)
  2162                              <1> 	; 16/07/2013
  2163                              <1> 	; mov 	[getctty], ah
  2164                              <1> 	;
  2165                              <1> 
  2166 00005F77 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn] 	; 28/07/2013
  2167                              <1> getc_n:
  2168                              <1> 	; 30/06/2015
  2169 00005F7D 08E4                <1> 	or	ah, ah
  2170 00005F7F 740D                <1> 	jz	short getc0 
  2171 00005F81 D0E4                <1> 	shl	ah, 1
  2172 00005F83 0FB6DC              <1> 	movzx	ebx, ah
  2173 00005F86 81C3[086B0000]      <1> 	add	ebx, ttychr
  2174 00005F8C EB05                <1> 	jmp	short getc1
  2175                              <1> getc0:
  2176 00005F8E BB[086B0000]        <1> 	mov	ebx, ttychr
  2177                              <1> getc1:
  2178 00005F93 668B0B              <1> 	mov	cx, [ebx] 	; ascii & scan code
  2179                              <1> 				; (by kb_int)	
  2180 00005F96 6609C9              <1> 	or	cx, cx
  2181 00005F99 7507                <1> 	jnz	short getc2
  2182 00005F9B 20C0                <1> 	and 	al, al
  2183 00005F9D 7415                <1> 	jz	short getc_s
  2184                              <1> 	;xor	ax, ax
  2185                              <1> 	; 24/12/2021
  2186 00005F9F 31C0                <1> 	xor	eax, eax
  2187 00005FA1 C3                  <1> 	retn
  2188                              <1> getc2:	
  2189 00005FA2 20C0                <1> 	and	al, al
  2190 00005FA4 6689C8              <1> 	mov	ax, cx
  2191 00005FA7 66B90000            <1> 	mov	cx, 0
  2192 00005FAB 7506                <1> 	jnz	short getc3
  2193                              <1> getc_sn:
  2194 00005FAD 66890B              <1> 	mov	[ebx], cx ; 0, reset
  2195 00005FB0 6639C8              <1> 	cmp	ax, cx  ; zf = 0
  2196                              <1> getc3:
  2197 00005FB3 C3                  <1> 	retn
  2198                              <1> getc_s:
  2199                              <1> 	; 12/11/2015
  2200                              <1> 	; 15/09/2015
  2201                              <1> 	; 01/07/2015
  2202                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2203                              <1> 	; 16/07/2013 - 14/02/2014 (Retro UNIX 8086 v1)
  2204                              <1> 	;
  2205                              <1> 	; tty  of the current process is not 
  2206                              <1> 	; current tty (ptty); so, current process only 
  2207                              <1> 	; can use keyboard input when its tty becomes 
  2208                              <1> 	; current tty (ptty).
  2209                              <1> 	; 'sleep' is for preventing an endless lock
  2210                              <1> 	; during this tty input request.
  2211                              <1> 	; (Because, the user is not looking at the video page
  2212                              <1> 	; of the process to undersand there is a keyboard
  2213                              <1> 	; input request.)
  2214                              <1> 	;
  2215                              <1> 	;((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2216                              <1> 	;
  2217                              <1> 	; 05/10/2013
  2218                              <1> 	; ah = byte ptr [u.ttyn] ; (tty number)
  2219                              <1> 	;
  2220                              <1> 	; 10/10/2013
  2221                              <1> gcw0:
  2222 00005FB4 B10A                <1> 	mov	cl, 10 ; ch = 0
  2223                              <1> gcw1:	
  2224                              <1> 	; 12/11/2015
  2225 00005FB6 E824DCFFFF          <1> 	call intract ; jumps to 'sysexit' if [u.quit] = FFFFh
  2226                              <1> 	; 10/10/2013
  2227 00005FBB E86CEFFFFF          <1> 	call	idle
  2228 00005FC0 668B03              <1> 	mov	ax, [ebx] 	; ascii & scan code
  2229                              <1> 				; (by kb_int)
  2230 00005FC3 6609C0              <1> 	or	ax, ax
  2231                              <1> ;	jnz	short gcw3
  2232 00005FC6 7519                <1> 	jnz	short gcw2 ; 15/09/2015
  2233                              <1> 	; 30/06/2015
  2234 00005FC8 FEC9                <1> 	dec	cl
  2235 00005FCA 75EA                <1> 	jnz	short gcw1
  2236                              <1> 	;
  2237 00005FCC 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn] 	; 20/10/2013
  2238                              <1> ;	; 10/12/2013
  2239                              <1> ;	cmp 	ah, [ptty]
  2240                              <1> ;	jne	short gcw2
  2241                              <1> ;	; 14/02/2014
  2242                              <1> ;	cmp	byte [u.uno], 1
  2243                              <1> ;	jna	short gcw0		
  2244                              <1> ;gcw2:
  2245 00005FD2 E8E2EFFFFF          <1> 	call	sleep
  2246                              <1> 	;
  2247                              <1> 	; 20/09/2013
  2248 00005FD7 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn]
  2249 00005FDD 30C0                <1> 	xor 	al, al
  2250 00005FDF EB9C                <1> 	jmp	short getc_n
  2251                              <1> ;gcw3:
  2252                              <1> gcw2: 	; 15/09/2015
  2253                              <1> 	; 10/10/2013
  2254 00005FE1 30C9                <1> 	xor	cl, cl
  2255 00005FE3 EBC8                <1> 	jmp	short getc_sn
  2256                              <1> 
  2257                              <1> putc:	
  2258                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2259                              <1> 	; 13/08/2015
  2260                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2261                              <1> 	; 15/05/2013 - 27/07/2014 (Retro UNIX 8086 v1)
  2262                              <1> 	;
  2263                              <1> 	; Retro UNIX 8086 v1 modification !
  2264                              <1> 	; 
  2265                              <1> 	; 'putc' puts a character 
  2266                              <1> 	;	 onto requested (tty) video page or
  2267                              <1> 	;	 serial port
  2268                              <1> 	; INPUTS ->
  2269                              <1> 	;     AL = ascii code of the character
  2270                              <1> 	;     AH = video page (tty) number (0 to 7)
  2271                              <1> 	;			  (8 is COM1, 9 is COM2)	
  2272                              <1> 	; OUTPUTS ->
  2273                              <1> 	;    (If AL input is 1) ZF=1 -> 'empty buffer' (no chars)
  2274                              <1> 	;      			ZF=0 -> AX has (current) character
  2275                              <1> 	;     cf=0 and AH = 0 -> no error
  2276                              <1> 	;     cf=1 and AH > 0 -> error (only for COM1 and COM2)		 			
  2277                              <1> 	; 
  2278                              <1> 	; Original UNIX V1 'putc': 
  2279                              <1> 	;     put a character at the end of character list
  2280                              <1> 	;
  2281                              <1> 	; ((Modified registers: eAX, eBX, eCX, eDX, eSI, eDI))
  2282                              <1> 	;
  2283 00005FE5 80FC07              <1> 	cmp	ah, 7
  2284                              <1>         ;ja	sndc
  2285 00005FE8 770A                <1>         ja      short sndc ; 24/12/2024
  2286                              <1> 	; 30/06/2015
  2287 00005FEA 0FB6DC              <1> 	movzx	ebx, ah
  2288                              <1> 	; 13/08/2015
  2289 00005FED B407                <1> 	mov	ah, 07h ; black background, light gray character color
  2290 00005FEF E9D2B3FFFF          <1> 	jmp	write_tty ; 'video.inc'
  2291                              <1> 
  2292                              <1> sndc:   ; <Send character>
  2293                              <1> 	;
  2294                              <1> 	; 12/01/2022
  2295                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2296                              <1> 	; 17/11/2015
  2297                              <1> 	; 16/11/2015
  2298                              <1> 	; 11/11/2015
  2299                              <1> 	; 10/11/2015
  2300                              <1> 	; 09/11/2015
  2301                              <1> 	; 08/11/2015
  2302                              <1> 	; 07/11/2015
  2303                              <1> 	; 06/11/2015 (serial4.asm, 'sendchr')	
  2304                              <1> 	; 29/10/2015
  2305                              <1> 	; 30/06/2015 (Retro UNIX 386 v1 - Beginning)
  2306                              <1> 	; 14/05/2013 - 28/07/2014 (Retro UNIX 8086 v1)
  2307                              <1> 	;
  2308                              <1> 	; Retro UNIX 8086 v1 feature only !
  2309                              <1> 	;
  2310                              <1> 	; ah = [u.ttyn]
  2311                              <1> 	;
  2312                              <1> 	; 30/06/2015
  2313 00005FF4 80EC08              <1> 	sub	ah, 8 ; ; 0 = tty8 or 1 = tty9
  2314                              <1> 	; 07/11/2015
  2315 00005FF7 0FB6DC              <1> 	movzx	ebx, ah ; serial port index (0 or 1)
  2316                              <1> sndc0:
  2317                              <1> 	; 07/11/2015
  2318 00005FFA E808F0FFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2319 00005FFF 7405                <1> 	jz	short sndc1
  2320 00006001 E8D9DBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2321                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2322                              <1> sndc1:
  2323                              <1> 	; 16/11/2015
  2324                              <1> 	;mov	cx, ax	; *** al = character (to be sent)
  2325                              <1> 	; 24/12/2021
  2326 00006006 89C1                <1> 	mov	ecx, eax ; *** al = character (to be sent)
  2327                              <1> sndcx:
  2328 00006008 8A83[4A6B0000]      <1> 	mov	al, [ebx+schar] ; last sent character
  2329 0000600E 8AA3[486B0000]      <1> 	mov	ah, [ebx+rchar] ; last received character
  2330                              <1> 	;
  2331                              <1> 	; 17/11/2015
  2332                              <1> 	; check 'request for response' status
  2333 00006014 80BB[446B0000]00    <1> 	cmp	byte [ebx+req_resp], 0
  2334 0000601B 740A                <1> 	jz	short query
  2335                              <1> response:
  2336 0000601D FE05[476B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2337 00006023 B0FF                <1> 	mov	al, 0FFh	 
  2338 00006025 EB14                <1> 	jmp	short sndc3
  2339                              <1> query:
  2340 00006027 08C0                <1> 	or 	al, al  ; 0 = query (also end of text)
  2341 00006029 750E                <1> 	jnz 	short sndc2 ; normal character
  2342                              <1> 	;cmp 	ah, 0FFh     ; is it responded by terminal ?
  2343                              <1> 	;je	short sndc2  ; yes, already responded
  2344                              <1> 	; 16/11/2015
  2345                              <1> 	; query: request for response (again)
  2346 0000602B 8883[486B0000]      <1> 	mov	[ebx+rchar], al ; 0 ; reset
  2347 00006031 FE05[476B0000]      <1> 	inc 	byte [comqr] ; query or response status
  2348 00006037 EB02                <1> 	jmp	short sndc3
  2349                              <1> sndc2:
  2350 00006039 88C8                <1> 	mov	al, cl 	; *** character (to be sent)
  2351                              <1> sndc3:
  2352 0000603B 8883[4A6B0000]      <1> 	mov	[ebx+schar], al ; current character (to be sent)
  2353 00006041 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2354                              <1> 	; 30/06/2015
  2355 00006043 E832D5FFFF          <1> 	call	sp_status ; get serial port status
  2356                              <1> 	; AL = Line status, AH = Modem status
  2357                              <1> 	; 07/11/2015
  2358 00006048 A880                <1> 	test	al, 80h
  2359 0000604A 7504                <1> 	jnz	short sndc4
  2360 0000604C A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2361 0000604E 751A                <1> 	jnz	short sndc5
  2362                              <1> sndc4: 	; Check line status again
  2363                              <1> 	; 16/11/2015
  2364                              <1> 	;push	cx
  2365                              <1> 	; 24/12/2021
  2366 00006050 51                  <1> 	push	ecx
  2367                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2368                              <1> 	; 12/01/2022
  2369 00006051 31C9                <1> 	xor	ecx, ecx
  2370 00006053 B106                <1> 	mov	cl, 6
  2371 00006055 E863B4FFFF          <1> 	call	WAITF
  2372                              <1> 	;pop	cx
  2373                              <1> 	; 24/12/1021
  2374 0000605A 59                  <1> 	pop	ecx
  2375                              <1> 	;
  2376 0000605B 88D8                <1> 	mov	al, bl ; 0 or 1 (serial port index)
  2377 0000605D E818D5FFFF          <1> 	call	sp_status ; get serial port status
  2378                              <1> 	; 16/11/2015
  2379                              <1> 	; 09/11/2015
  2380                              <1> 	; 08/11/2015
  2381 00006062 A880                <1> 	test	al, 80h	; time out error
  2382 00006064 7565                <1>         jnz     short sndc7
  2383 00006066 A820                <1> 	test	al, 20h	; Transmitter holding register empty ?
  2384 00006068 7461                <1>         jz	short sndc7
  2385                              <1> sndc5:  
  2386 0000606A 8A83[4A6B0000]      <1> 	mov	al, [ebx+schar] ; character (to be sent)
  2387 00006070 66BAF803            <1> 	mov	dx, 3F8h   ; data port (COM2)
  2388 00006074 28DE                <1> 	sub	dh, bl
  2389 00006076 EE                  <1> 	out	dx, al	   ; send on serial port
  2390                              <1> 	; 10/11/2015
  2391                              <1> 	; delay for 3*30 (3*(15..80)) micro seconds
  2392                              <1> 	; (to improve text flow to the terminal)
  2393                              <1> 	; ('diskette.inc': 'WAITF')
  2394                              <1> 	; Uses port 61h, bit 4 to have CPU speed independent waiting.
  2395                              <1> 	; (refresh periods = 1 per 30 microseconds on most machines)
  2396                              <1> 	;push	cx
  2397                              <1> 	; 24/12/2021
  2398 00006077 51                  <1> 	push	ecx
  2399                              <1> 	;mov	ecx, 6 ; 6*30 micro seconds (~5556 chars/second)
  2400                              <1> 	; 12/01/2022
  2401 00006078 29C9                <1> 	sub	ecx, ecx
  2402 0000607A B106                <1> 	mov	cl, 6
  2403 0000607C E83CB4FFFF          <1> 	call	WAITF
  2404                              <1> 	;pop	cx
  2405                              <1> 	; 24/12/1021
  2406 00006081 59                  <1> 	pop	ecx
  2407                              <1>     	;
  2408                              <1> 	; 07/11/2015
  2409 00006082 88D8                <1> 	mov	al, bl ; al = 0 (tty8) or 1 (tty9)
  2410                              <1> 	;
  2411 00006084 E8F1D4FFFF          <1> 	call	sp_status ; get serial port status
  2412                              <1> 	; AL = Line status, AH = Modem status
  2413                              <1> 	;
  2414 00006089 E879EFFFFF          <1> 	call	isintr ; quit (ctrl+break) check
  2415 0000608E 7405                <1> 	jz	short sndc6
  2416 00006090 E84ADBFFFF          <1> 	call	intract ; quit (ctrl+break) check
  2417                              <1> 	; CPU will jump to 'sysexit' if 'u.quit' = 0FFFFh (yes)
  2418                              <1> sndc6:
  2419 00006095 3C80                <1> 	cmp	al, 80h
  2420 00006097 7332                <1> 	jnb	short sndc7		
  2421                              <1> 	;
  2422 00006099 803D[476B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2423 000060A0 7244                <1> 	jb	short sndc8 	; no, normal character
  2424 000060A2 883D[476B0000]      <1> 	mov 	byte [comqr], bh ; 0 ; reset
  2425                              <1> 	; 17/11/2015
  2426 000060A8 E87FEEFFFF          <1> 	call	idle
  2427                              <1> 	;
  2428 000060AD 38BB[4A6B0000]      <1> 	cmp	[ebx+schar], bh ; 0 ; query ?
  2429                              <1>         ;ja	sndc2       ; response (will be followed by
  2430                              <1> 			    ; a normal character)
  2431                              <1> 	; 24/12/2021
  2432 000060B3 7602                <1> 	jna	short sndc_10
  2433 000060B5 EB82                <1> 	jmp	sndc2
  2434                              <1> sndc_10:
  2435                              <1> 	; Query request must be responded by the terminal
  2436                              <1> 	; before sending a normal character !
  2437 000060B7 53                  <1> 	push	ebx
  2438                              <1> 	;push	cx ; *** cl = character (to be sent)
  2439                              <1> 	; 24/12/2021
  2440 000060B8 51                  <1> 	push	ecx ; *** cl = character (to be sent)
  2441 000060B9 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn]
  2442 000060BF E8F5EEFFFF          <1> 	call	sleep ; this process will be awakened by
  2443                              <1> 		      ; received data available interrupt
  2444                              <1> 	;pop	cx ; *** cl = character (to be sent)
  2445                              <1> 	; 24/12/2021
  2446 000060C4 59                  <1> 	pop	ecx ; *** cl = character (to be sent) 
  2447 000060C5 5B                  <1> 	pop	ebx
  2448 000060C6 E93DFFFFFF          <1>         jmp	sndcx
  2449                              <1> sndc7:
  2450                              <1> 	 ; 16/11/2015
  2451 000060CB 803D[476B0000]01    <1> 	cmp	byte [comqr], 1 ; 'query or response' ?
  2452 000060D2 7213                <1> 	jb	short sndc9 	; no
  2453                              <1> 	;
  2454 000060D4 88BB[486B0000]      <1> 	mov	[ebx+rchar], bh ; 0 ; reset
  2455 000060DA 88BB[4A6B0000]      <1> 	mov	[ebx+schar], bh ; 0 ; reset
  2456                              <1> 	;
  2457 000060E0 883D[476B0000]      <1> 	mov	byte [comqr], bh ; 0 ; reset  
  2458                              <1> sndc8:
  2459 000060E6 F5                  <1> 	cmc  ; jnc -> jc, jb -> jnb
  2460                              <1> sndc9:
  2461                              <1> 	; AL = Line status, AH = Modem status
  2462 000060E7 C3                  <1> 	retn
  2463                              <1> 
  2464                              <1> get_cpos:
  2465                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2466                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2467                              <1> 	;
  2468                              <1> 	; INPUT -> bl = video page number
  2469                              <1> 	; RETURN -> dx = cursor position
  2470                              <1> 
  2471 000060E8 53                  <1> 	push	ebx
  2472 000060E9 83E30F              <1> 	and	ebx, 0Fh ; 07h ; tty0 to tty7
  2473 000060EC D0E3                <1> 	shl	bl, 1
  2474 000060EE 81C3[F66A0000]      <1> 	add	ebx, cursor_posn
  2475 000060F4 668B13              <1> 	mov	dx, [ebx]
  2476 000060F7 5B                  <1> 	pop	ebx
  2477 000060F8 C3                  <1> 	retn
  2478                              <1> 
  2479                              <1> read_ac_current:
  2480                              <1> 	; 29/06/2015 (Retro UNIX 386 v1)
  2481                              <1> 	; 04/12/2013 (Retro UNIX 8086 v1 - 'sysgtty')
  2482                              <1> 	;
  2483                              <1> 	; INPUT -> bl = video page number
  2484                              <1> 	; RETURN -> ax = character (al) and attribute (ah)
  2485                              <1> 
  2486 000060F9 E832B4FFFF          <1> 	call 	find_position ; 'video.inc'
  2487                              <1> 	; dx = status port
  2488                              <1> 	; esi = cursor location/address
  2489 000060FE 81C600800B00        <1> 	add	esi, 0B8000h	; 30/08/2014 (Retro UNIX 386 v1)
  2490 00006104 668B06              <1> 	mov 	ax, [esi]	; get the character and attribute
  2491 00006107 C3                  <1> 	retn
  2492                              <1> 
  2493                              <1> syssleep:
  2494                              <1> 	; 29/06/2015 - (Retro UNIX 386 v1)
  2495                              <1> 	; 11/06/2014 - (Retro UNIX 8086 v1)
  2496                              <1> 	;
  2497                              <1> 	; Retro UNIX 8086 v1 feature only
  2498                              <1> 	; (INPUT -> none)
  2499                              <1> 	;
  2500 00006108 0FB61D[E76E0000]    <1> 	movzx	ebx, byte [u.uno] ; process number
  2501 0000610F 8AA3[F76B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; current/console tty
  2502 00006115 E89FEEFFFF          <1> 	call	sleep
  2503 0000611A E9D3D9FFFF          <1> 	jmp	sysret
  2504                              <1> 
  2505                              <1> 	; 27/02/2022
  2506                              <1> 	; (u1.s, 'wttyc' & 'wpc_clr')
  2507                              <1> %if 0
  2508                              <1> 
  2509                              <1> vp_clr:
  2510                              <1> 	; Reset/Clear Video Page
  2511                              <1> 	;
  2512                              <1> 	; 24/12/2021 - (Retro UNIX 386 v1.1)
  2513                              <1> 	; 30/06/2015 - (Retro UNIX 386 v1)
  2514                              <1> 	; 21/05/2013 - 30/10/2013(Retro UNIX 8086 v1) (U0.ASM)
  2515                              <1> 	;
  2516                              <1> 	; Retro UNIX 8086 v1 feature only !
  2517                              <1> 	;
  2518                              <1> 	; INPUTS -> 
  2519                              <1> 	;   BL = video page number	 
  2520                              <1> 	;
  2521                              <1> 	; OUTPUT ->
  2522                              <1> 	;   none
  2523                              <1> 	; ((Modified registers: eAX, BH, eCX, eDX, eSI, eDI))
  2524                              <1> 	;
  2525                              <1> 	; 04/12/2013
  2526                              <1> 	sub	al, al
  2527                              <1> 	; al = 0 (clear video page)
  2528                              <1> 	; bl = video page
  2529                              <1> 	mov	ah, 07h
  2530                              <1> 	; ah = 7 (attribute/color)
  2531                              <1> 	;xor 	cx, cx ; 0, left upper column (cl) & row (cl)
  2532                              <1> 	; 24/12/2021
  2533                              <1> 	xor	ecx, ecx
  2534                              <1> 	mov	dx, 184Fh ; right lower column & row (dl=24, dh=79)
  2535                              <1> 	call	scroll_up
  2536                              <1> 	; bl = video page
  2537                              <1> 	;xor	dx, dx ; 0 (cursor position) 
  2538                              <1> 	; 24/12/2021
  2539                              <1> 	xor	edx, edx 
  2540                              <1> 	jmp 	set_cpos
  2541                              <1> 
  2542                              <1> %endif
  2543                              <1> 
  2544                              <1> sysmsg:
  2545                              <1> 	; 24/12/2021 (Retro UNIX 386 v1.1)
  2546                              <1> 	; 11/11/2015
  2547                              <1> 	; 01/07/2015 - (Retro UNIX 386 v1 feature only!)
  2548                              <1> 	; Print user-application message on user's console tty
  2549                              <1> 	;
  2550                              <1> 	; Input -> EBX = Message address
  2551                              <1> 	;	   ECX = Message length (max. 255)
  2552                              <1> 	;	   DL = Color (IBM PC Rombios color attributes)
  2553                              <1> 	;
  2554 0000611F 81F9FF000000        <1> 	cmp	ecx, MAX_MSG_LEN ; 255
  2555                              <1> 	;ja	sysret ; nothing to do with big message size
  2556 00006125 7779                <1> 	ja	short sysmsg8 ; 24/12/2021
  2557 00006127 08C9                <1> 	or	cl, cl
  2558                              <1> 	;jz	sysret
  2559 00006129 7475                <1> 	jz	short sysmsg8 ; 24/12/2021
  2560 0000612B 20D2                <1> 	and	dl, dl
  2561 0000612D 7502                <1> 	jnz	short sysmsg0
  2562 0000612F B207                <1> 	mov	dl, 07h ; default color
  2563                              <1> 		; (black background, light gray character)
  2564                              <1> sysmsg0:
  2565 00006131 891D[B86E0000]      <1> 	mov	[u.base], ebx
  2566 00006137 8815[076B0000]      <1> 	mov	[ccolor], dl ; color attributes
  2567 0000613D 89E5                <1> 	mov	ebp, esp
  2568 0000613F 31DB                <1> 	xor	ebx, ebx ; 0
  2569 00006141 891D[C06E0000]      <1> 	mov	[u.nread], ebx ; 0
  2570                              <1> 	;
  2571 00006147 381D[FF6E0000]      <1> 	cmp	[u.kcall], bl ; 0
  2572 0000614D 7772                <1> 	ja	short sysmsgk ; Temporary (01/07/2015)
  2573                              <1> 	;
  2574 0000614F 890D[BC6E0000]      <1> 	mov	[u.count], ecx
  2575 00006155 41                  <1> 	inc	ecx ; + 00h ; ASCIIZ
  2576                              <1> 	; 24/12/2021
  2577                              <1> 	; (dword alignment for esp)
  2578 00006156 F6C103              <1> 	test	cl, 3
  2579 00006159 7404                <1> 	jz	short sysmsg_7
  2580 0000615B 80C903              <1> 	or	cl, 3
  2581 0000615E 41                  <1> 	inc	ecx
  2582                              <1> sysmsg_7:
  2583 0000615F 29CC                <1> 	sub	esp, ecx
  2584 00006161 89E7                <1> 	mov	edi, esp
  2585 00006163 89E6                <1> 	mov	esi, esp
  2586 00006165 66891D[FD6E0000]    <1> 	mov	[u.pcount], bx ; reset page (phy. addr.) counter
  2587                              <1> 	; 11/11/2015
  2588 0000616C 8A25[C86E0000]      <1> 	mov 	ah, [u.ttyp] ; recent open tty
  2589                              <1> 	; 0 = none
  2590 00006172 FECC                <1> 	dec	ah
  2591 00006174 790C                <1> 	jns	short sysmsg1 
  2592 00006176 8A1D[E76E0000]      <1> 	mov	bl, [u.uno] ; process number	
  2593 0000617C 8AA3[F76B0000]      <1> 	mov	ah, [ebx+p.ttyc-1] ; user's (process's) console tty
  2594                              <1> sysmsg1:
  2595 00006182 8825[EC6E0000]      <1> 	mov	[u.ttyn], ah
  2596                              <1> sysmsg2:
  2597 00006188 E884F5FFFF          <1> 	call	cpass
  2598 0000618D 7416                <1> 	jz	short sysmsg5
  2599 0000618F AA                  <1> 	stosb
  2600 00006190 20C0                <1> 	and	al, al
  2601 00006192 75F4                <1> 	jnz	short sysmsg2
  2602                              <1> sysmsg3:
  2603 00006194 80FC07              <1> 	cmp	ah, 7 ; tty number
  2604 00006197 7711                <1> 	ja	short sysmsg6 ; serial port
  2605 00006199 E83E000000          <1> 	call	print_cmsg
  2606                              <1> sysmsg4:
  2607 0000619E 89EC                <1> 	mov	esp, ebp	
  2608                              <1> sysmsg8: ; 24/12/2021	
  2609 000061A0 E94DD9FFFF          <1> 	jmp	sysret
  2610                              <1> sysmsg5:
  2611 000061A5 C60700              <1> 	mov	byte [edi], 0
  2612 000061A8 EBEA                <1> 	jmp	short sysmsg3
  2613                              <1> sysmsg6:
  2614 000061AA 8A06                <1> 	mov	al, [esi]
  2615 000061AC E843FEFFFF          <1> 	call	sndc
  2616 000061B1 72EB                <1> 	jc	short sysmsg4
  2617 000061B3 803E00              <1> 	cmp	byte [esi], 0  ; 0 is stop character
  2618 000061B6 76E6                <1> 	jna	short sysmsg4
  2619 000061B8 46                  <1> 	inc 	esi
  2620 000061B9 8A25[EC6E0000]      <1> 	mov	ah, [u.ttyn]
  2621 000061BF EBE9                <1> 	jmp	short sysmsg6
  2622                              <1> 
  2623                              <1> sysmsgk: ; Temporary (01/07/2015)
  2624                              <1> 	; The message has been sent by Kernel (ASCIIZ string)
  2625                              <1> 	; (ECX -character count- will not be considered)
  2626 000061C1 8B35[B86E0000]      <1> 	mov	esi, [u.base]
  2627 000061C7 8A25[066B0000]      <1> 	mov	ah, [ptty] ; present/current screen (video page)
  2628 000061CD 8825[EC6E0000]      <1> 	mov	[u.ttyn], ah
  2629 000061D3 C605[FF6E0000]00    <1> 	mov	byte [u.kcall], 0
  2630 000061DA EBB8                <1> 	jmp	short sysmsg3
  2631                              <1> 	
  2632                              <1> print_cmsg: 
  2633                              <1> 	; 01/07/2015 (retro UNIX 386 v1 feature only !)
  2634                              <1> 	;
  2635                              <1> 	; print message (on user's console tty) 
  2636                              <1> 	;	with requested color
  2637                              <1> 	;
  2638                              <1> 	; INPUTS:
  2639                              <1> 	;	esi = message address
  2640                              <1> 	;	[u.ttyn] = tty number (0 to 7)
  2641                              <1> 	;	[ccolor] = color attributes (IBM PC BIOS colors)
  2642                              <1> 	;
  2643 000061DC AC                  <1> 	lodsb
  2644                              <1> pcmsg1:
  2645 000061DD 56                  <1> 	push 	esi
  2646 000061DE 0FB61D[EC6E0000]    <1>         movzx   ebx, byte [u.ttyn]
  2647 000061E5 8A25[076B0000]      <1> 	mov	ah, [ccolor]
  2648 000061EB E8D6B1FFFF          <1> 	call 	write_tty
  2649 000061F0 5E                  <1> 	pop	esi
  2650 000061F1 AC                  <1> 	lodsb
  2651 000061F2 20C0                <1> 	and 	al, al  ; 0
  2652 000061F4 75E7                <1> 	jnz 	short pcmsg1
  2653 000061F6 C3                  <1> 	retn
  2654                              <1> 
  2655                              <1> sysgeterr:
  2656                              <1> 	; 16/02/2022 - Retro UNIX 386 v1.1
  2657                              <1> 	; 09/12/2015
  2658                              <1> 	; 21/09/2015 - (Retro UNIX 386 v1 feature only!)
  2659                              <1> 	; Get last error number or page fault count
  2660                              <1> 	; (for debugging)
  2661                              <1> 	;
  2662                              <1> 	; Input -> EBX = return type
  2663                              <1> 	;	   0 = last error code (which is in 'u.error')	
  2664                              <1> 	;	   FFFFFFFFh = page fault count for running process
  2665                              <1> 	;	   FFFFFFFEh = total page fault count
  2666                              <1> 	;	   1 .. FFFFFFFDh = undefined 
  2667                              <1> 	;
  2668                              <1> 	; Output -> EAX = last error number or page fault count
  2669                              <1> 	;	   (depending on EBX input)
  2670                              <1> 	; 	
  2671 000061F7 21DB                <1> 	and 	ebx, ebx
  2672 000061F9 750F                <1> 	jnz	short glerr_2
  2673                              <1> glerr_0:
  2674 000061FB A1[ED6E0000]        <1> 	mov	eax, [u.error]
  2675                              <1> glerr_1:
  2676 00006200 A3[986E0000]        <1> 	mov	[u.r0], eax
  2677                              <1>  	;retn
  2678                              <1> 	; 16/02/2022 (BugFix)
  2679 00006205 E9E8D8FFFF          <1> 	jmp	sysret
  2680                              <1> glerr_2:
  2681 0000620A 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0, FFFFFFFEh -> FFFFFFFFh
  2682 0000620B 74FD                <1> 	jz	short glerr_2 ; page fault count for process
  2683 0000620D 43                  <1> 	inc	ebx ; FFFFFFFFh -> 0	
  2684 0000620E 75EB                <1> 	jnz	short glerr_0
  2685 00006210 A1[906B0000]        <1> 	mov	eax, [PF_Count] ; total page fault count
  2686 00006215 EBE9                <1>         jmp     short glerr_1
  2687                              <1> glerr_3:
  2688 00006217 A1[016F0000]        <1> 	mov 	eax, [u.pfcount]
  2689 0000621C EBE2                <1> 	jmp	short glerr_1
  2105                                  
  2106                                  ; 07/03/2015
  2107                                  ; Temporary Code
  2108                                  display_disks:
  2109 0000621E 803D[CE650000]00        	cmp 	byte [fd0_type], 0
  2110 00006225 7605                    	jna 	short ddsks1
  2111 00006227 E87D000000              	call	pdskm
  2112                                  ddsks1:
  2113 0000622C 803D[CF650000]00        	cmp	byte [fd1_type], 0
  2114 00006233 760C                    	jna	short ddsks2
  2115 00006235 C605[BF670000]31        	mov	byte [dskx], '1'
  2116 0000623C E868000000              	call	pdskm
  2117                                  ddsks2:
  2118 00006241 803D[D0650000]00        	cmp	byte [hd0_type], 0
  2119 00006248 7654                    	jna	short ddsk6
  2120 0000624A 66C705[BD670000]68-     	mov	word [dsktype], 'hd'
  2120 00006252 64                 
  2121 00006253 C605[BF670000]30        	mov	byte [dskx], '0'
  2122 0000625A E84A000000              	call	pdskm
  2123                                  ddsks3:
  2124 0000625F 803D[D1650000]00        	cmp	byte [hd1_type], 0
  2125 00006266 7636                    	jna	short ddsk6
  2126 00006268 C605[BF670000]31        	mov	byte [dskx], '1'
  2127 0000626F E835000000              	call	pdskm
  2128                                  ddsks4:
  2129 00006274 803D[D2650000]00        	cmp	byte [hd2_type], 0
  2130 0000627B 7621                    	jna	short ddsk6
  2131 0000627D C605[BF670000]32        	mov	byte [dskx], '2'
  2132 00006284 E820000000              	call	pdskm
  2133                                  ddsks5:
  2134 00006289 803D[D3650000]00        	cmp	byte [hd3_type], 0
  2135 00006290 760C                    	jna	short ddsk6
  2136 00006292 C605[BF670000]33        	mov	byte [dskx], '3'
  2137 00006299 E80B000000              	call	pdskm
  2138                                  ddsk6:
  2139 0000629E BE[CE670000]            	mov	esi, nextline
  2140 000062A3 E806000000              	call	pdskml
  2141                                  pdskm_ok:
  2142 000062A8 C3                      	retn
  2143                                  pdskm:
  2144 000062A9 BE[BB670000]            	mov	esi, dsk_ready_msg
  2145                                  pdskml:	
  2146 000062AE AC                      	lodsb
  2147 000062AF 08C0                    	or	al, al
  2148 000062B1 74F5                    	jz	short pdskm_ok
  2149 000062B3 56                      	push	esi
  2150 000062B4 31DB                    	xor	ebx, ebx ; 0
  2151                                  			; Video page 0 (bl=0)
  2152 000062B6 B407                    	mov	ah, 07h ; Black background, 
  2153                                  			; light gray forecolor
  2154 000062B8 E809B1FFFF              	call	write_tty
  2155 000062BD 5E                      	pop	esi
  2156 000062BE EBEE                    	jmp	short pdskml
  2157                                  
  2158                                  align 16
  2159                                  
  2160                                  gdt:	; Global Descriptor Table
  2161                                  	; (30/07/2015, conforming cs)
  2162                                  	; (26/03/2015)
  2163                                  	; (24/03/2015, tss)
  2164                                  	; (19/03/2015)
  2165                                  	; (29/12/2013)
  2166                                  	;
  2167 000062C0 0000000000000000        	dw 0, 0, 0, 0		; NULL descriptor
  2168                                  	; 18/08/2014
  2169                                  			; 8h kernel code segment, base = 00000000h		
  2170 000062C8 FFFF0000009ACF00        	dw 0FFFFh, 0, 9A00h, 00CFh	; KCODE
  2171                                  			; 10h kernel data segment, base = 00000000h	
  2172 000062D0 FFFF00000092CF00        	dw 0FFFFh, 0, 9200h, 00CFh	; KDATA
  2173                                  			; 1Bh user code segment, base address = 400000h ; CORE
  2174 000062D8 FFFB000040FACF00        	dw 0FBFFh, 0, 0FA40h, 00CFh	; UCODE 
  2175                                  			; 23h user data segment, base address = 400000h ; CORE
  2176 000062E0 FFFB000040F2CF00        	dw 0FBFFh, 0, 0F240h, 00CFh	; UDATA
  2177                                  			; Task State Segment
  2178 000062E8 6700                    	dw 0067h ; Limit = 103 ; (104-1, tss size = 104 byte, 
  2179                                  			       ;  no IO permission in ring 3)
  2180                                  gdt_tss0:
  2181 000062EA 0000                    	dw 0  ; TSS base address, bits 0-15 
  2182                                  gdt_tss1:
  2183 000062EC 00                      	db 0  ; TSS base address, bits 16-23 
  2184                                  	      		; 49h	
  2185 000062ED E9                      	db 11101001b ; E9h => P=1/DPL=11/0/1/0/B/1 --> B = Task is busy (1)
  2186 000062EE 00                      	db 0 ; G/0/0/AVL/LIMIT=0000 ; (Limit bits 16-19 = 0000) (G=0, 1 byte)
  2187                                  gdt_tss2:
  2188 000062EF 00                      	db 0  ; TSS base address, bits 24-31 
  2189                                  
  2190                                  gdt_end:
  2191                                  	;; 9Ah = 1001 1010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2192                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2193                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2194                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2195                                  
  2196                                  	;; 92h = 1001 0010b (GDT byte 5) P=1/DPL=00/1/TYPE=1010, 
  2197                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2198                                  		; P= Present, DPL=0=ring 0,  1= user (0= system)
  2199                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2200                                  		; W= Writeable, A= Accessed
  2201                                  	
  2202                                  	;; FAh = 1111 1010b (GDT byte 5) P=1/DPL=11/1/TYPE=1010, 
  2203                                  					;; Type= 1 (code)/C=0/R=1/A=0
  2204                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2205                                  		; 1= Code C= non-Conforming, R= Readable, A = Accessed
  2206                                  
  2207                                  	;; F2h = 1111 0010b (GDT byte 5) P=1/DPL=11/1/TYPE=0010, 
  2208                                  					;; Type= 0 (data)/E=0/W=1/A=0
  2209                                  		; P= Present, DPL=3=ring 3,  1= user (0= system)
  2210                                  		; 0= Data E= Expansion direction (1= down, 0= up)
  2211                                  	
  2212                                  	;; CFh = 1100 1111b (GDT byte 6) G=1/B=1/0/AVL=0, Limit=1111b (3)
  2213                                  
  2214                                  		;; Limit = FFFFFh (=> FFFFFh+1= 100000h) // bits 0-15, 48-51 //
  2215                                  		;	 = 100000h * 1000h (G=1) = 4GB
  2216                                  		;; Limit = FFBFFh (=> FFBFFh+1= FFC00h) // bits 0-15, 48-51 //
  2217                                  		;	 = FFC00h * 1000h (G=1) = 4GB - 4MB
  2218                                  		; G= Granularity (1= 4KB), B= Big (32 bit), 
  2219                                  		; AVL= Available to programmers	
  2220                                  
  2221                                  gdtd:
  2222 000062F0 2F00                            dw gdt_end - gdt - 1    ; Limit (size)
  2223 000062F2 [C0620000]                      dd gdt			; Address of the GDT
  2224                                  
  2225                                  	; 20/08/2014
  2226                                  idtd:
  2227 000062F6 FF01                            dw idt_end - idt - 1    ; Limit (size)
  2228 000062F8 [70680000]                      dd idt			; Address of the IDT
  2229                                  
  2230                                  Align 4
  2231                                  
  2232                                  	; 21/08/2014
  2233                                  ilist:
  2234                                  	;times 	32 dd cpu_except ; INT 0 to INT 1Fh
  2235                                  	;
  2236                                  	; Exception list
  2237                                  	; 25/08/2014	
  2238 000062FC [25080000]              	dd	exc0	; 0h,  Divide-by-zero Error
  2239 00006300 [2C080000]              	dd	exc1	
  2240 00006304 [33080000]              	dd 	exc2	
  2241 00006308 [3A080000]              	dd	exc3	
  2242 0000630C [3E080000]              	dd	exc4	
  2243 00006310 [42080000]              	dd	exc5	
  2244 00006314 [46080000]              	dd 	exc6	; 06h,  Invalid Opcode
  2245 00006318 [4A080000]              	dd	exc7	
  2246 0000631C [4E080000]              	dd	exc8	
  2247 00006320 [52080000]              	dd	exc9	
  2248 00006324 [56080000]              	dd 	exc10	
  2249 00006328 [5A080000]              	dd	exc11
  2250 0000632C [5E080000]              	dd	exc12
  2251 00006330 [62080000]              	dd	exc13	; 0Dh, General Protection Fault
  2252 00006334 [66080000]              	dd 	exc14	; 0Eh, Page Fault
  2253 00006338 [6A080000]              	dd	exc15
  2254 0000633C [6E080000]              	dd	exc16
  2255 00006340 [72080000]              	dd	exc17
  2256 00006344 [76080000]              	dd 	exc18
  2257 00006348 [7A080000]              	dd	exc19
  2258 0000634C [7E080000]              	dd 	exc20
  2259 00006350 [82080000]              	dd	exc21
  2260 00006354 [86080000]              	dd	exc22
  2261 00006358 [8A080000]              	dd	exc23
  2262 0000635C [8E080000]              	dd 	exc24
  2263 00006360 [92080000]              	dd	exc25
  2264 00006364 [96080000]              	dd	exc26
  2265 00006368 [9A080000]              	dd	exc27
  2266 0000636C [9E080000]              	dd 	exc28
  2267 00006370 [A2080000]              	dd	exc29
  2268 00006374 [A6080000]              	dd 	exc30
  2269 00006378 [AA080000]              	dd	exc31
  2270                                  	; Interrupt list
  2271 0000637C [60060000]              	dd	timer_int	; INT 20h
  2272                                  		;dd	irq0	
  2273 00006380 [640B0000]              	dd	keyb_int	; 27/08/2014
  2274                                  		;dd	irq1
  2275 00006384 [7F070000]              	dd	irq2
  2276                                  		; COM2 int
  2277 00006388 [83070000]              	dd	irq3
  2278                                  		; COM1 int
  2279 0000638C [8E070000]              	dd	irq4
  2280 00006390 [99070000]              	dd	irq5
  2281                                  ;DISKETTE_INT: ;06/02/2015
  2282 00006394 [49250000]              	dd	fdc_int		; 16/02/2015, IRQ 6 handler	
  2283                                  		;dd	irq6
  2284                                  ; Default IRQ 7 handler against spurious IRQs (from master PIC)
  2285                                  ; 25/02/2015 (source: http://wiki.osdev.org/8259_PIC)
  2286 00006398 [150B0000]              	dd	default_irq7	; 25/02/2015
  2287                                  		;dd	irq7
  2288                                  ; Real Time Clock Interrupt
  2289 0000639C [B3090000]              	dd	rtc_int		; 23/02/2015, IRQ 8 handler
  2290                                  		;dd	irq8	; INT 28h
  2291 000063A0 [A9070000]              	dd	irq9
  2292 000063A4 [AD070000]              	dd	irq10
  2293 000063A8 [B1070000]              	dd	irq11
  2294 000063AC [B5070000]              	dd	irq12
  2295 000063B0 [B9070000]              	dd	irq13
  2296                                  ;HDISK_INT1:  ;06/02/2015 	
  2297 000063B4 [6F2D0000]              	dd	hdc1_int 	; 21/02/2015, IRQ 14 handler		
  2298                                  		;dd	irq14
  2299                                  ;HDISK_INT2:  ;06/02/2015
  2300 000063B8 [922D0000]              	dd	hdc2_int 	; 21/02/2015, IRQ 15 handler		
  2301                                  		;dd	irq15	; INT 2Fh
  2302                                  		; 14/08/2015
  2303 000063BC [DA390000]              	dd	sysent		; INT 30h (system calls)
  2304                                  	
  2305                                  	;dd	ignore_int
  2306 000063C0 00000000                	dd	0
  2307                                  
  2308                                  ;;;
  2309                                  ;;; 11/03/2015
  2310                                  %include 'kybdata.inc'	; KEYBOARD (BIOS) DATA
  2311                              <1> ; Retro UNIX 386 v1 Kernel - KYBDATA.INC
  2312                              <1> ; Last Modification: 11/03/2015
  2313                              <1> ;		 (Data Section for 'KEYBOARD.INC')	
  2314                              <1> ;
  2315                              <1> ; ///////// KEYBOARD DATA ///////////////
  2316                              <1> 
  2317                              <1> ; 05/12/2014
  2318                              <1> ; 04/12/2014 (derived from pc-xt-286 bios source code -1986-) 
  2319                              <1> ; 03/06/86  KEYBOARD BIOS
  2320                              <1> 
  2321                              <1> ;---------------------------------------------------------------------------------
  2322                              <1> ;	KEY IDENTIFICATION SCAN TABLES
  2323                              <1> ;---------------------------------------------------------------------------------
  2324                              <1> 
  2325                              <1> ;-----	TABLES FOR ALT CASE ------------
  2326                              <1> ;-----	ALT-INPUT-TABLE 
  2327 000063C4 524F50514B          <1> K30:	db	82,79,80,81,75
  2328 000063C9 4C4D474849          <1> 	db	76,77,71,72,73		; 10 NUMBER ON KEYPAD
  2329                              <1> ;-----	SUPER-SHIFT-TABLE 
  2330 000063CE 101112131415        <1> 	db	16,17,18,19,20,21	; A-Z TYPEWRITER CHARS
  2331 000063D4 161718191E1F        <1> 	db	22,23,24,25,30,31
  2332 000063DA 202122232425        <1> 	db	32,33,34,35,36,37
  2333 000063E0 262C2D2E2F30        <1> 	db	38,44,45,46,47,48
  2334 000063E6 3132                <1> 	db	49,50
  2335                              <1> 
  2336                              <1> ;-----	TABLE OF SHIFT KEYS AND MASK VALUES
  2337                              <1> ;-----	KEY_TABLE 
  2338 000063E8 52                  <1> _K6:    db      INS_KEY                 ; INSERT KEY
  2339 000063E9 3A4546381D          <1> 	db	CAPS_KEY,NUM_KEY,SCROLL_KEY,ALT_KEY,CTL_KEY
  2340 000063EE 2A36                <1>         db      LEFT_KEY,RIGHT_KEY
  2341                              <1> _K6L    equ     $-_K6
  2342                              <1> 
  2343                              <1> ;-----	MASK_TABLE
  2344 000063F0 80                  <1> _K7:    db      INS_SHIFT               ; INSERT MODE SHIFT
  2345 000063F1 4020100804          <1> 	db	CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT,ALT_SHIFT,CTL_SHIFT
  2346 000063F6 0201                <1> 	db	LEFT_SHIFT,RIGHT_SHIFT
  2347                              <1> 
  2348                              <1> ;-----	TABLES FOR CTRL CASE		;---- CHARACTERS ------
  2349 000063F8 1BFF00FFFFFF        <1> _K8:	db	27,-1,0,-1,-1,-1	; Esc, 1, 2, 3, 4, 5
  2350 000063FE 1EFFFFFFFF1F        <1> 	db 	30,-1,-1,-1,-1,31	; 6, 7, 8, 9, 0, -
  2351 00006404 FF7FFF111705        <1> 	db	-1,127,-1,17,23,5	; =, Bksp, Tab, Q, W, E
  2352 0000640A 12141915090F        <1> 	db	18,20,25,21,9,15	; R, T, Y, U, I, O
  2353 00006410 101B1D0AFF01        <1> 	db	16,27,29,10,-1,1	; P, [, ], Enter, Ctrl, A
  2354 00006416 13040607080A        <1> 	db	19,4,6,7,8,10		; S, D, F, G, H, J
  2355 0000641C 0B0CFFFFFFFF        <1> 	db	11,12,-1,-1,-1,-1	; K, L, :, ', `, LShift
  2356 00006422 1C1A18031602        <1> 	db	28,26,24,3,22,2		; Bkslash, Z, X, C, V, B
  2357 00006428 0E0DFFFFFFFF        <1> 	db	14,13,-1,-1,-1,-1	; N, M, ,, ., /, RShift
  2358 0000642E 96FF20FF            <1> 	db	150,-1,' ',-1		; *, ALT, Spc, CL
  2359                              <1> 	;				;----- FUNCTIONS ------		
  2360 00006432 5E5F60616263        <1> 	db 	94,95,96,97,98,99	; F1 - F6
  2361 00006438 64656667FFFF        <1> 	db	100,101,102,103,-1,-1	; F7 - F10, NL, SL
  2362 0000643E 778D848E738F        <1> 	db	119,141,132,142,115,143	; Home, Up, PgUp, -, Left, Pad5
  2363 00006444 749075917692        <1> 	db 	116,144,117,145,118,146 ; Right, +, End, Down, PgDn, Ins
  2364 0000644A 93FFFFFF898A        <1> 	db	147,-1,-1,-1,137,138	; Del, SysReq, Undef, WT, F11, F12
  2365                              <1> 
  2366                              <1> ;-----	TABLES FOR LOWER CASE ----------
  2367 00006450 1B3132333435363738- <1> K10:	db 	27,'1234567890-=',8,9
  2367 00006459 39302D3D0809        <1>
  2368 0000645F 71776572747975696F- <1> 	db 	'qwertyuiop[]',13,-1,'asdfghjkl;',39
  2368 00006468 705B5D0DFF61736466- <1>
  2368 00006471 67686A6B6C3B27      <1>
  2369 00006478 60FF5C7A786376626E- <1> 	db	96,-1,92,'zxcvbnm,./',-1,'*',-1,' ',-1
  2369 00006481 6D2C2E2FFF2AFF20FF  <1>
  2370                              <1> ;-----	LC TABLE SCAN
  2371 0000648A 3B3C3D3E3F          <1> 	db	59,60,61,62,63		; BASE STATE OF F1 - F10
  2372 0000648F 4041424344          <1> 	db	64,65,66,67,68
  2373 00006494 FFFF                <1> 	db	-1,-1			; NL, SL
  2374                              <1> 
  2375                              <1> ;-----	KEYPAD TABLE
  2376 00006496 474849FF4BFF        <1> K15:	db	71,72,73,-1,75,-1	; BASE STATE OF KEYPAD KEYS
  2377 0000649C 4DFF4F50515253      <1> 	db	77,-1,79,80,81,82,83
  2378 000064A3 FFFF5C8586          <1> 	db	-1,-1,92,133,134	; SysRq, Undef, WT, F11, F12
  2379                              <1> 
  2380                              <1> ;-----	TABLES FOR UPPER CASE ----------
  2381 000064A8 1B21402324255E262A- <1> K11:	db 	27,'!@#$%',94,'&*()_+',8,0
  2381 000064B1 28295F2B0800        <1>
  2382 000064B7 51574552545955494F- <1> 	db 	'QWERTYUIOP{}',13,-1,'ASDFGHJKL:"'
  2382 000064C0 507B7D0DFF41534446- <1>
  2382 000064C9 47484A4B4C3A22      <1>
  2383 000064D0 7EFF7C5A584356424E- <1> 	db	126,-1,'|ZXCVBNM<>?',-1,'*',-1,' ',-1
  2383 000064D9 4D3C3E3FFF2AFF20FF  <1>
  2384                              <1> ;-----	UC TABLE SCAN
  2385 000064E2 5455565758          <1> K12:	db	84,85,86,87,88		; SHIFTED STATE OF F1 - F10
  2386 000064E7 595A5B5C5D          <1> 	db	89,90,91,92,93
  2387 000064EC FFFF                <1> 	db	-1,-1			; NL, SL
  2388                              <1> 
  2389                              <1> ;-----	NUM STATE TABLE
  2390 000064EE 3738392D3435362B31- <1> K14:	db 	'789-456+1230.'		; NUMLOCK STATE OF KEYPAD KEYS
  2390 000064F7 3233302E            <1>
  2391                              <1> 	;
  2392 000064FB FFFF7C8788          <1> 	db	-1,-1,124,135,136	; SysRq, Undef, WT, F11, F12
  2393                              <1> 
  2394                              <1> Align	4
  2395                              <1> ;----------------------------------------
  2396                              <1> ;	VIDEO DISPLAY DATA AREA		;
  2397                              <1> ;----------------------------------------
  2398 00006500 03                  <1> CRT_MODE	db	3	; CURRENT DISPLAY MODE (TYPE)
  2399 00006501 29                  <1> CRT_MODE_SET	db	29h	; CURRENT SETTING OF THE 3X8 REGISTER
  2400                              <1> 				; (29h default setting for video mode 3)
  2401                              <1> 				; Mode Select register Bits
  2402                              <1> 				;   BIT 0 - 80x25 (1), 40x25 (0)
  2403                              <1> 				;   BIT 1 - ALPHA (0), 320x200 GRAPHICS (1)
  2404                              <1> 				;   BIT 2 - COLOR (0), BW (1)
  2405                              <1> 				;   BIT 3 - Video Sig. ENABLE (1), DISABLE (0)
  2406                              <1> 				;   BIT 4 - 640x200 B&W Graphics Mode (1)
  2407                              <1> 				;   BIT 5 - ALPHA mode BLINKING (1)
  2408                              <1> 				;   BIT 6, 7 - Not Used
  2409                              <1> 
  2410                              <1> ; Mode 0 - 2Ch = 101100b	; 40x25 text, 16 gray colors
  2411                              <1> ; Mode 1 - 28h = 101000b	; 40x25 text, 16 fore colors, 8 back colors
  2412                              <1> ; Mode 2 - 2Dh = 101101b	; 80x25 text, 16 gray colors	
  2413                              <1> ; MODE 3 - 29h = 101001b	; 80x25 text, 16 fore color, 8 back color
  2414                              <1> ; Mode 4 - 2Ah = 101010b	; 320x200 graphics, 4 colors
  2415                              <1> ; Mode 5 - 2Eh = 101110b	; 320x200 graphics, 4 gray colors
  2416                              <1> ; Mode 6 - 1Eh = 011110b	; 640x200 graphics, 2 colors
  2417                              <1> ; Mode 7 - 29h = 101001b	; 80x25 text, black & white colors
  2418                              <1> ; Mode & 37h = Video signal OFF
  2419                              <1> 			
  2420                              <1> 
  2421                              <1> ; 26/08/2014
  2422                              <1> ; Retro UNIX 8086 v1 - UNIX.ASM (03/03/2014)
  2423                              <1> ; Derived from IBM "pc-at" 
  2424                              <1> ; rombios source code (06/10/1985)
  2425                              <1> ; 'dseg.inc'
  2426                              <1> 
  2427                              <1> ;---------------------------------------;
  2428                              <1> ;	SYSTEM DATA AREA		;
  2429                              <1> ;----------------------------------------
  2430 00006502 00                  <1> BIOS_BREAK	db	0		; BIT 7=1 IF BREAK KEY HAS BEEN PRESSED
  2431                              <1> 
  2432                              <1> ;----------------------------------------
  2433                              <1> ;	KEYBOARD DATA AREAS		;
  2434                              <1> ;----------------------------------------
  2435                              <1> 
  2436 00006503 00                  <1> KB_FLAG		db	0		; KEYBOARD SHIFT STATE AND STATUS FLAGS
  2437 00006504 00                  <1> KB_FLAG_1	db	0		; SECOND BYTE OF KEYBOARD STATUS
  2438 00006505 00                  <1> KB_FLAG_2	db	0		; KEYBOARD LED FLAGS
  2439 00006506 00                  <1> KB_FLAG_3	db	0		; KEYBOARD MODE STATE AND TYPE FLAGS
  2440 00006507 00                  <1> ALT_INPUT	db	0		; STORAGE FOR ALTERNATE KEY PAD ENTRY
  2441 00006508 [18650000]          <1> BUFFER_START	dd	KB_BUFFER 	; OFFSET OF KEYBOARD BUFFER START
  2442 0000650C [38650000]          <1> BUFFER_END	dd	KB_BUFFER + 32	; OFFSET OF END OF BUFFER
  2443 00006510 [18650000]          <1> BUFFER_HEAD	dd	KB_BUFFER 	; POINTER TO HEAD OF KEYBOARD BUFFER
  2444 00006514 [18650000]          <1> BUFFER_TAIL	dd	KB_BUFFER 	; POINTER TO TAIL OF KEYBOARD BUFFER
  2445                              <1> ; ------	HEAD = TAIL	INDICATES THAT THE BUFFER IS EMPTY
  2446 00006518 0000<rep 10h>       <1> KB_BUFFER	times	16 dw 0		; ROOM FOR 16 SCAN CODE ENTRIES
  2447                              <1> 
  2448                              <1> ; /// End Of KEYBOARD DATA ///
  2311                                  %include 'vidata.inc'	; VIDEO (BIOS) DATA
  2312                              <1> ; Retro UNIX 386 v1 Kernel - VIDATA.INC
  2313                              <1> ; Last Modification: 11/03/2015
  2314                              <1> ;		    (Data section for 'VIDEO.INC')	
  2315                              <1> ;
  2316                              <1> ; ///////// VIDEO DATA ///////////////
  2317                              <1> 
  2318                              <1> video_params:
  2319                              <1> 	; 02/09/2014 (Retro UNIX 386 v1)
  2320                              <1> 	;ORGS.ASM ----- 06/10/85   COMPATIBILITY MODULE
  2321                              <1> 	; VIDEO MODE 3
  2322 00006538 71505A0A1F0619      <1> 	db	71h,50h,5Ah,0Ah,1Fh,6,19h	; SET UP FOR 80X25
  2323 0000653F 1C02070607          <1> 	db	1Ch,2,7,6,7	; cursor start = 6, cursor stop = 7
  2324 00006544 00000000            <1> 	db	0,0,0,0
  2325                              <1> 
  2326                              <1> ; /// End Of VIDEO DATA ///
  2312                                  %include 'diskdata.inc'	; DISK (BIOS) DATA (initialized)
  2313                              <1> ; Retro UNIX 386 v1 Kernel - DISKDATA.INC
  2314                              <1> ; Last Modification: 11/03/2015
  2315                              <1> ;	(Initialized Disk Parameters Data section for 'DISKIO.INC') 
  2316                              <1> ;
  2317                              <1> ; *****************************************************************************
  2318                              <1> 
  2319                              <1> ;----------------------------------------
  2320                              <1> ;	80286 INTERRUPT LOCATIONS	:
  2321                              <1> ;	REFERENCED BY POST & BIOS	:
  2322                              <1> ;----------------------------------------
  2323                              <1> 
  2324 00006548 [AB650000]          <1> DISK_POINTER:	dd	MD_TBL6		; Pointer to Diskette Parameter Table
  2325                              <1> 
  2326                              <1> ; IBM PC-XT Model 286 source code ORGS.ASM (06/10/85) - 14/12/2014
  2327                              <1> ;----------------------------------------------------------------
  2328                              <1> ; DISK_BASE							:
  2329                              <1> ;	THIS IS THE SET OF PARAMETERS REQUIRED FOR		:
  2330                              <1> ;	DISKETTE OPERATION. THEY ARE POINTED AT BY THE		:
  2331                              <1> ;	DATA VARIABLE @DISK_POINTER. TO MODIFY THE PARAMETERS,	:
  2332                              <1> ;	BUILD ANOTHER PARAMETER BLOCK AND POINT AT IT		:
  2333                              <1> ;----------------------------------------------------------------
  2334                              <1> 
  2335                              <1> ;DISK_BASE:	
  2336                              <1> ;	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2337                              <1> ;	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2338                              <1> ;	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2339                              <1> ;	DB	2		; 512 BYTES/SECTOR
  2340                              <1> ;	;DB	15		; EOT (LAST SECTOR ON TRACK)
  2341                              <1> ;	db	18		; (EOT for 1.44MB diskette)
  2342                              <1> ;	DB	01BH		; GAP LENGTH
  2343                              <1> ;	DB	0FFH		; DTL
  2344                              <1> ;	;DB	054H		; GAP LENGTH FOR FORMAT
  2345                              <1> ;	db	06ch		; (for 1.44MB dsikette)
  2346                              <1> ;	DB	0F6H		; FILL BYTE FOR FORMAT
  2347                              <1> ;	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2348                              <1> ;	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2349                              <1> 
  2350                              <1> ;----------------------------------------
  2351                              <1> ;	ROM BIOS DATA AREAS		:
  2352                              <1> ;----------------------------------------
  2353                              <1> 
  2354                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2355                              <1> 
  2356                              <1> ;@EQUIP_FLAG	DW	?		; INSTALLED HARDWARE FLAGS
  2357                              <1> 
  2358                              <1> ;----------------------------------------
  2359                              <1> ;	DISKETTE DATA AREAS		:
  2360                              <1> ;----------------------------------------
  2361                              <1> 
  2362                              <1> ;@SEEK_STATUS	DB	?		; DRIVE RECALIBRATION STATUS
  2363                              <1> ;					; BIT 3-0 = DRIVE 3-0 RECALIBRATION
  2364                              <1> ;					; BEFORE NEXT SEEK IF BIT IS = 0
  2365                              <1> ;@MOTOR_STATUS	DB	?		; MOTOR STATUS
  2366                              <1> ;					; BIT 3-0 = DRIVE 3-0 CURRENTLY RUNNING
  2367                              <1> ;					; BIT 7 = CURRENT OPERATION IS A WRITE
  2368                              <1> ;@MOTOR_COUNT	DB	?		; TIME OUT COUNTER FOR MOTOR(S) TURN OFF
  2369                              <1> ;@DSKETTE_STATUS DB	?		; RETURN CODE STATUS BYTE
  2370                              <1> ;					; CMD_BLOCK  IN STACK FOR DISK OPERATION
  2371                              <1> ;@NEC_STATUS	DB	7 DUP(?)	; STATUS BYTES FROM DISKETTE OPERATION
  2372                              <1> 
  2373                              <1> ;----------------------------------------
  2374                              <1> ;	POST AND BIOS WORK DATA AREA	:
  2375                              <1> ;----------------------------------------
  2376                              <1> 
  2377                              <1> ;@INTR_FLAG	DB	?		; FLAG INDICATING AN INTERRUPT HAPPENED
  2378                              <1> 
  2379                              <1> ;----------------------------------------
  2380                              <1> ;	TIMER DATA AREA 		:
  2381                              <1> ;----------------------------------------
  2382                              <1> 
  2383                              <1> ; 17/12/2014  (IRQ 0 - INT 08H)
  2384                              <1> ;TIMER_LOW	equ	46Ch		; Timer ticks (counter)  @ 40h:006Ch
  2385                              <1> ;TIMER_HIGH	equ	46Eh		; (18.2 timer ticks per second)
  2386                              <1> ;TIMER_OFL	equ	470h		; Timer - 24 hours flag  @ 40h:0070h
  2387                              <1> 
  2388                              <1> ;----------------------------------------
  2389                              <1> ;	ADDITIONAL MEDIA DATA		:
  2390                              <1> ;----------------------------------------
  2391                              <1> 
  2392                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2393                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2394                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2395                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2396                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2397                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2398                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2399                              <1> 
  2400                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2401                              <1> 
  2402                              <1> ;--------------------------------------------------------
  2403                              <1> ;	DRIVE TYPE TABLE				:
  2404                              <1> ;--------------------------------------------------------
  2405                              <1> 		; 16/02/2015 (unix386.s, 32 bit modifications)
  2406                              <1> DR_TYPE:
  2407 0000654C 01                  <1> 		DB	01		;DRIVE TYPE, MEDIA TABLE
  2408                              <1>                 ;DW      MD_TBL1
  2409 0000654D [6A650000]          <1> 		dd	MD_TBL1
  2410 00006551 82                  <1> 		DB	02+BIT7ON
  2411                              <1> 		;DW      MD_TBL2
  2412 00006552 [77650000]          <1>                 dd      MD_TBL2
  2413 00006556 02                  <1> DR_DEFAULT:	DB	02
  2414                              <1>                 ;DW      MD_TBL3
  2415 00006557 [84650000]          <1> 		dd      MD_TBL3
  2416 0000655B 03                  <1> 		DB	03
  2417                              <1>                 ;DW      MD_TBL4
  2418 0000655C [91650000]          <1> 		dd      MD_TBL4
  2419 00006560 84                  <1> 		DB	04+BIT7ON
  2420                              <1>                 ;DW      MD_TBL5
  2421 00006561 [9E650000]          <1> 		dd      MD_TBL5
  2422 00006565 04                  <1> 		DB	04
  2423                              <1>                 ;DW      MD_TBL6
  2424 00006566 [AB650000]          <1> 		dd      MD_TBL6
  2425                              <1> DR_TYPE_E       equ $                   ; END OF TABLE
  2426                              <1> ;DR_CNT		EQU	(DR_TYPE_E-DR_TYPE)/3
  2427                              <1> DR_CNT		equ	(DR_TYPE_E-DR_TYPE)/5
  2428                              <1> ;--------------------------------------------------------
  2429                              <1> ;	MEDIA/DRIVE PARAMETER TABLES			:
  2430                              <1> ;--------------------------------------------------------
  2431                              <1> ;--------------------------------------------------------
  2432                              <1> ;	360 KB MEDIA IN 360 KB DRIVE			:
  2433                              <1> ;--------------------------------------------------------
  2434                              <1> MD_TBL1:        
  2435 0000656A DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2436 0000656B 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2437 0000656C 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2438 0000656D 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2439 0000656E 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2440 0000656F 2A                  <1> 	DB	02AH		; GAP LENGTH
  2441 00006570 FF                  <1> 	DB	0FFH		; DTL
  2442 00006571 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2443 00006572 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2444 00006573 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2445 00006574 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2446 00006575 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2447 00006576 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2448                              <1> ;--------------------------------------------------------
  2449                              <1> ;	360 KB MEDIA IN 1.2 MB DRIVE			:
  2450                              <1> ;--------------------------------------------------------
  2451                              <1> MD_TBL2:        
  2452 00006577 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2453 00006578 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2454 00006579 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2455 0000657A 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2456 0000657B 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2457 0000657C 2A                  <1> 	DB	02AH		; GAP LENGTH
  2458 0000657D FF                  <1> 	DB	0FFH		; DTL
  2459 0000657E 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2460 0000657F F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2461 00006580 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2462 00006581 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2463 00006582 27                  <1> 	DB	39		; MAX. TRACK NUMBER
  2464 00006583 40                  <1> 	DB	RATE_300	; DATA TRANSFER RATE
  2465                              <1> ;--------------------------------------------------------
  2466                              <1> ;	1.2 MB MEDIA IN 1.2 MB DRIVE			:
  2467                              <1> ;--------------------------------------------------------
  2468                              <1> MD_TBL3:
  2469 00006584 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2470 00006585 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2471 00006586 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2472 00006587 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2473 00006588 0F                  <1> 	DB	15		; EOT (LAST SECTOR ON TRACK)
  2474 00006589 1B                  <1> 	DB	01BH		; GAP LENGTH
  2475 0000658A FF                  <1> 	DB	0FFH		; DTL
  2476 0000658B 54                  <1> 	DB	054H		; GAP LENGTH FOR FORMAT
  2477 0000658C F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2478 0000658D 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2479 0000658E 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2480 0000658F 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2481 00006590 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2482                              <1> ;--------------------------------------------------------
  2483                              <1> ;	720 KB MEDIA IN 720 KB DRIVE			:
  2484                              <1> ;--------------------------------------------------------
  2485                              <1> MD_TBL4:
  2486 00006591 DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2487 00006592 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2488 00006593 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2489 00006594 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2490 00006595 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2491 00006596 2A                  <1> 	DB	02AH		; GAP LENGTH
  2492 00006597 FF                  <1> 	DB	0FFH		; DTL
  2493 00006598 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2494 00006599 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2495 0000659A 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2496 0000659B 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2497 0000659C 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2498 0000659D 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2499                              <1> ;--------------------------------------------------------
  2500                              <1> ;	720 KB MEDIA IN 1.44 MB DRIVE			:
  2501                              <1> ;--------------------------------------------------------
  2502                              <1> MD_TBL5:
  2503 0000659E DF                  <1> 	DB	11011111B	; SRT=D, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2504 0000659F 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2505 000065A0 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2506 000065A1 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2507 000065A2 09                  <1> 	DB	09		; EOT (LAST SECTOR ON TRACK)
  2508 000065A3 2A                  <1> 	DB	02AH		; GAP LENGTH
  2509 000065A4 FF                  <1> 	DB	0FFH		; DTL
  2510 000065A5 50                  <1> 	DB	050H		; GAP LENGTH FOR FORMAT
  2511 000065A6 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2512 000065A7 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2513 000065A8 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2514 000065A9 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2515 000065AA 80                  <1> 	DB	RATE_250	; DATA TRANSFER RATE
  2516                              <1> ;--------------------------------------------------------
  2517                              <1> ;	1.44 MB MEDIA IN 1.44 MB DRIVE			:
  2518                              <1> ;--------------------------------------------------------
  2519                              <1> MD_TBL6:
  2520 000065AB AF                  <1> 	DB	10101111B	; SRT=A, HD UNLOAD=0F - 1ST SPECIFY BYTE
  2521 000065AC 02                  <1> 	DB	2		; HD LOAD=1, MODE=DMA - 2ND SPECIFY BYTE
  2522 000065AD 25                  <1> 	DB	MOTOR_WAIT	; WAIT TIME AFTER OPERATION TILL MOTOR OFF
  2523 000065AE 02                  <1> 	DB	2		; 512 BYTES/SECTOR
  2524 000065AF 12                  <1> 	DB	18		; EOT (LAST SECTOR ON TRACK)
  2525 000065B0 1B                  <1> 	DB	01BH		; GAP LENGTH
  2526 000065B1 FF                  <1> 	DB	0FFH		; DTL
  2527 000065B2 6C                  <1> 	DB	06CH		; GAP LENGTH FOR FORMAT
  2528 000065B3 F6                  <1> 	DB	0F6H		; FILL BYTE FOR FORMAT
  2529 000065B4 0F                  <1> 	DB	15		; HEAD SETTLE TIME (MILLISECONDS)
  2530 000065B5 08                  <1> 	DB	8		; MOTOR START TIME (1/8 SECONDS)
  2531 000065B6 4F                  <1> 	DB	79		; MAX. TRACK NUMBER
  2532 000065B7 00                  <1> 	DB	RATE_500	; DATA TRANSFER RATE
  2533                              <1> 
  2534                              <1> 
  2535                              <1> ; << diskette.inc >>
  2536                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2537                              <1> ;
  2538                              <1> ;----------------------------------------
  2539                              <1> ;	ROM BIOS DATA AREAS		:
  2540                              <1> ;----------------------------------------
  2541                              <1> 
  2542                              <1> ;DATA		SEGMENT AT 40H		; ADDRESS= 0040:0000
  2543                              <1> 
  2544                              <1> ;----------------------------------------
  2545                              <1> ;	FIXED DISK DATA AREAS		:
  2546                              <1> ;----------------------------------------
  2547                              <1> 
  2548                              <1> ;DISK_STATUS1:	DB	0		; FIXED DISK STATUS
  2549                              <1> ;HF_NUM:		DB	0		; COUNT OF FIXED DISK DRIVES
  2550                              <1> ;CONTROL_BYTE:	DB	0		; HEAD CONTROL BYTE
  2551                              <1> ;@PORT_OFF	DB	?		;  RESERVED (PORT OFFSET)
  2552                              <1> 
  2553                              <1> ;----------------------------------------
  2554                              <1> ;	ADDITIONAL MEDIA DATA		:
  2555                              <1> ;----------------------------------------
  2556                              <1> 
  2557                              <1> ;@LASTRATE	DB	?		; LAST DISKETTE DATA RATE SELECTED
  2558                              <1> ;HF_STATUS	DB	0		; STATUS REGISTER
  2559                              <1> ;HF_ERROR	DB	0		; ERROR REGISTER
  2560                              <1> ;HF_INT_FLAG	DB	0		; FIXED DISK INTERRUPT FLAG
  2561                              <1> ;HF_CNTRL	DB	0		; COMBO FIXED DISK/DISKETTE CARD BIT 0=1
  2562                              <1> ;@DSK_STATE	DB	?		; DRIVE 0 MEDIA STATE
  2563                              <1> ;		DB	?		; DRIVE 1 MEDIA STATE
  2564                              <1> ;		DB	?		; DRIVE 0 OPERATION START STATE
  2565                              <1> ;		DB	?		; DRIVE 1 OPERATION START STATE
  2566                              <1> ;@DSK_TRK	DB	?		; DRIVE 0 PRESENT CYLINDER
  2567                              <1> ;		DB	?		; DRIVE 1 PRESENT CYLINDER
  2568                              <1> 
  2569                              <1> ;DATA		ENDS			; END OF BIOS DATA SEGMENT
  2570                              <1> ;
  2571                              <1> ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2572                              <1> 
  2573                              <1> ERR_TBL:
  2574 000065B8 E0                  <1> 	db	NO_ERR
  2575 000065B9 024001BB            <1> 	db	BAD_ADDR_MARK,BAD_SEEK,BAD_CMD,UNDEF_ERR
  2576 000065BD 04BB100A            <1> 	db	RECORD_NOT_FND,UNDEF_ERR,BAD_ECC,BAD_SECTOR
  2577                              <1> 
  2578                              <1> ; 17/12/2014 (mov ax, [cfd])
  2579                              <1> ; 11/12/2014
  2580 000065C1 00                  <1> cfd:		db 0			; current floppy drive (for GET_PARM)
  2581                              <1> ; 17/12/2014				; instead of 'DISK_POINTER'
  2582 000065C2 01                  <1> pfd:		db 1			; previous floppy drive (for GET_PARM)
  2583                              <1> 					; (initial value of 'pfd 
  2584                              <1> 					; must be different then 'cfd' value
  2585                              <1> 					; to force updating/initializing
  2586                              <1> 					; current drive parameters) 
  2587 000065C3 90                  <1> align 2
  2588                              <1> 
  2589 000065C4 F001                <1> HF_PORT:	dw 	1F0h  ; Default = 1F0h
  2590                              <1> 			      ; (170h)
  2591 000065C6 F603                <1> HF_REG_PORT:	dw	3F6h  ; HF_PORT + 206h
  2592                              <1> 
  2593                              <1> ; 05/01/2015 
  2594 000065C8 00                  <1> hf_m_s:         db      0     ; (0 = Master, 1 = Slave)
  2595                              <1> 
  2596                              <1> ; *****************************************************************************
  2313                                  ;;;
  2314                                  
  2315 000065C9 90                      Align 2
  2316                                  
  2317                                  ; 12/11/2014 (Retro UNIX 386 v1)
  2318 000065CA 00                      boot_drv:    db 0 ; boot drive number (physical)
  2319                                  ; 24/11/2014
  2320 000065CB 00                      drv:	     db 0 
  2321 000065CC 00                      last_drv:    db 0 ; last hdd
  2322 000065CD 00                      hdc:         db 0  ; number of hard disk drives
  2323                                  		     ; (present/detected)
  2324                                  ;
  2325                                  ; 24/11/2014 (Retro UNIX 386 v1)
  2326                                  ; Physical drive type & flags
  2327 000065CE 00                      fd0_type:    db 0  ; floppy drive type
  2328 000065CF 00                      fd1_type:    db 0  ; 4 = 1.44 Mb, 80 track, 3.5" (18 spt)
  2329                                  		     ; 6 = 2.88 Mb, 80 track, 3.5" (36 spt)
  2330                                  		     ; 3 = 720 Kb, 80 track, 3.5" (9 spt)
  2331                                  		     ; 2 = 1.2 Mb, 80 track, 5.25" (15 spt)
  2332                                  		     ; 1 = 360 Kb, 40 track, 5.25" (9 spt)		
  2333 000065D0 00                      hd0_type:    db 0  ; EDD status for hd0 (bit 7 = present flag)
  2334 000065D1 00                      hd1_type:    db 0  ; EDD status for hd1 (bit 7 = present flag)
  2335 000065D2 00                      hd2_type:    db 0  ; EDD status for hd2 (bit 7 = present flag)
  2336 000065D3 00                      hd3_type:    db 0  ; EDD status for hd3 (bit 7 = present flag)
  2337                                  		     ; bit 0 - Fixed disk access subset supported
  2338                                  		     ; bit 1 - Drive locking and ejecting
  2339                                  		     ; bit 2 - Enhanced disk drive support
  2340                                  		     ; bit 3 = Reserved (64 bit EDD support)
  2341                                  		     ; (If bit 0 is '1' Retro UNIX 386 v1
  2342                                  		     ; will interpret it as 'LBA ready'!)		
  2343                                  
  2344                                  ; 11/03/2015 - 10/07/2015
  2345 000065D4 000000000000000000-     drv.cylinders: dw 0,0,0,0,0,0,0
  2345 000065DD 0000000000         
  2346 000065E2 000000000000000000-     drv.heads:     dw 0,0,0,0,0,0,0
  2346 000065EB 0000000000         
  2347 000065F0 000000000000000000-     drv.spt:       dw 0,0,0,0,0,0,0
  2347 000065F9 0000000000         
  2348 000065FE 000000000000000000-     drv.size:      dd 0,0,0,0,0,0,0
  2348 00006607 000000000000000000-
  2348 00006610 000000000000000000-
  2348 00006619 00                 
  2349 0000661A 00000000000000          drv.status:    db 0,0,0,0,0,0,0
  2350 00006621 00000000000000          drv.error:     db 0,0,0,0,0,0,0		
  2351                                  ;
  2352                                  
  2353                                  ; 27/08/2014
  2354                                  scr_row:
  2355 00006628 E0810B00                	dd 0B8000h + 0A0h + 0A0h + 0A0h ; Row 3
  2356                                  scr_col:
  2357 0000662C 00000000                	dd 0
  2358                                  
  2359                                  ;; 14/08/2015
  2360                                  ;;msgPM:
  2361                                  ;;      db "Protected mode and paging are ENABLED ... ", 0
  2362                                  msgKVER:
  2363 00006630 526574726F20554E49-     	db "Retro UNIX 386 v1.1 - Kernel v0.2.1.2 [29/04/2022]", 0
  2363 00006639 58203338362076312E-
  2363 00006642 31202D204B65726E65-
  2363 0000664B 6C2076302E322E312E-
  2363 00006654 32205B32392F30342F-
  2363 0000665D 323032325D00       
  2364                                  
  2365 00006663 90                      Align 2
  2366                                  
  2367                                  ; 20/08/2014
  2368                                    ; /* This is the default interrupt "handler" :-) */ 
  2369                                    ; Linux v0.12 (head.s)
  2370                                  int_msg:
  2371 00006664 556E6B6E6F776E2069-     	db "Unknown interrupt ! ", 0
  2371 0000666D 6E7465727275707420-
  2371 00006676 212000             
  2372                                  
  2373 00006679 90                      Align 2  
  2374                                  
  2375                                  ; 21/08/2014
  2376                                  timer_msg:
  2377 0000667A 49525120302028494E-     	db "IRQ 0 (INT 20h) ! Timer Interrupt : "
  2377 00006683 542032306829202120-
  2377 0000668C 54696D657220496E74-
  2377 00006695 657272757074203A20 
  2378                                  tcountstr:
  2379 0000669E 303030303020            	db "00000 "
  2380 000066A4 00                      	db 0
  2381                                  
  2382 000066A5 90                      Align 2
  2383                                  	; 21/08/2014
  2384                                  exc_msg:
  2385 000066A6 435055206578636570-     	db "CPU exception ! "
  2385 000066AF 74696F6E202120     
  2386                                  excnstr: 		; 25/08/2014
  2387 000066B6 3F3F68202045495020-     	db "??h", "  EIP : "
  2387 000066BF 3A20               
  2388                                  EIPstr: ; 29/08/2014
  2389 000066C1 00<rep Ch>              	times 12 db 0
  2390                                  rtc_msg:
  2391 000066CD 5265616C2054696D65-     	db "Real Time Clock - "
  2391 000066D6 20436C6F636B202D20 
  2392                                  datestr:
  2393 000066DF 30302F30302F303030-     	db "00/00/0000"
  2393 000066E8 30                 
  2394 000066E9 20                      	db " "
  2395                                  daystr:
  2396 000066EA 44415920                	db "DAY "
  2397                                  timestr:	
  2398 000066EE 30303A30303A3030                db "00:00:00"
  2399 000066F6 20                      	db " "
  2400 000066F7 00                      	db 0 
  2401                                  
  2402                                  daytmp:
  2403                                  	; 28/02/2015
  2404 000066F8 3F3F3F2053554E204D-     	db "??? SUN MON TUE WED THU FRI SAT "
  2404 00006701 4F4E20545545205745-
  2404 0000670A 442054485520465249-
  2404 00006713 2053415420         
  2405                                  
  2406 00006718 FF                      ptime_seconds: db 0FFh
  2407                                  
  2408                                  	; 23/02/2015
  2409                                  	; 25/08/2014
  2410                                  ;scounter:
  2411                                  ;	db 5
  2412                                  ;	db 19
  2413                                  
  2414                                  ; 02/01/2022
  2415                                  ; 05/11/2014
  2416                                  ;msg_out_of_memory:
  2417                                  ;	db 	07h, 0Dh, 0Ah
  2418                                  ;       db	'Insufficient memory ! (Minimum 2 MB memory is needed.)'
  2419                                  ; 	db	0Dh, 0Ah, 0
  2420                                  	;
  2421                                  setup_error_msg:
  2422 00006719 0D0A                    	db 0Dh, 0Ah
  2423 0000671B 4469736B2053657475-     	db 'Disk Setup Error!' 
  2423 00006724 70204572726F7221   
  2424 0000672C 0D0A00                  	db 0Dh, 0Ah,0
  2425                                  
  2426                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2427                                  ;crt_ulc : db 0 ; upper left column (for scroll) 
  2428                                  ;	  db 0 ; upper left row (for scroll)	
  2429                                  
  2430                                  ;crt_lrc : db 79 ; lower right column (for scroll) 
  2431                                  ;	  db 24 ; lower right row (for scroll)
  2432                                  
  2433                                  
  2434                                  ; 06/11/2014 (Temporary Data)
  2435                                  ; Memory Information message
  2436                                  ; 14/08/2015
  2437                                  msg_memory_info:
  2438 0000672F 07                      	db	07h
  2439 00006730 0D0A                    	db	0Dh, 0Ah
  2440                                  	;db 	"MEMORY ALLOCATION INFO", 0Dh, 0Ah, 0Dh, 0Ah
  2441 00006732 546F74616C206D656D-     	db	"Total memory : "
  2441 0000673B 6F7279203A20       
  2442                                  mem_total_b_str: ; 10 digits
  2443 00006741 303030303030303030-     	db	"0000000000 bytes", 0Dh, 0Ah
  2443 0000674A 302062797465730D0A 
  2444 00006753 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2444 0000675C 202020202020202020 
  2445                                  mem_total_p_str: ; 7 digits
  2446 00006765 303030303030302070-     	db	"0000000 pages", 0Dh, 0Ah
  2446 0000676E 616765730D0A       
  2447 00006774 0D0A                    	db 	0Dh, 0Ah
  2448 00006776 46726565206D656D6F-     	db	"Free memory  : "
  2448 0000677F 727920203A20       
  2449                                  free_mem_b_str:  ; 10 digits
  2450 00006785 3F3F3F3F3F3F3F3F3F-     	db	"?????????? bytes", 0Dh, 0Ah
  2450 0000678E 3F2062797465730D0A 
  2451 00006797 202020202020202020-     	db	"               ", 20h, 20h, 20h
  2451 000067A0 202020202020202020 
  2452                                  free_mem_p_str:  ; 7 digits
  2453 000067A9 3F3F3F3F3F3F3F2070-     	db	"??????? pages", 0Dh, 0Ah
  2453 000067B2 616765730D0A       
  2454 000067B8 0D0A00                  	db	0Dh, 0Ah, 0
  2455                                  
  2456                                  dsk_ready_msg:
  2457 000067BB 0D0A                    	db 	0Dh, 0Ah
  2458                                  dsktype:
  2459 000067BD 6664                    	db	'fd'
  2460                                  dskx:
  2461 000067BF 30                      	db	'0'
  2462 000067C0 20                      	db	20h
  2463 000067C1 697320524541445920-     	db 	'is READY ...'
  2463 000067CA 2E2E2E             
  2464 000067CD 00                      	db 	0
  2465                                  nextline:
  2466 000067CE 0D0A00                  	db 	0Dh, 0Ah, 0
  2467                                  
  2468                                  ; KERNEL - SYSINIT Messages
  2469                                  ; 24/08/2015
  2470                                  ; 13/04/2015 - (Retro UNIX 386 v1 Beginning)
  2471                                  ; 14/07/2013
  2472                                  ;kernel_init_err_msg:
  2473                                  ;	db 0Dh, 0Ah
  2474                                  ;	db 07h
  2475                                  ;	db 'Kernel initialization ERROR !'
  2476                                  ;	db 0Dh, 0Ah, 0 
  2477                                  ; 24/08/2015
  2478                                  ;;; (temporary kernel init message has been removed
  2479                                  ;;;  from 'sys_init' code)
  2480                                  ;kernel_init_ok_msg: 
  2481                                  ;	db 0Dh, 0Ah
  2482                                  ;	db 07h
  2483                                  ;	db 'Welcome to Retro UNIX 386 v1.1 Operating System !'
  2484                                  ;	db 0Dh, 0Ah
  2485                                  ;       db 'by Erdogan Tan - 04/02/2016 (v0.2.1.0)'
  2486                                  ;	db 0Dh, 0Ah, 0
  2487                                  panic_msg:
  2488 000067D1 0D0A07                  	db 0Dh, 0Ah, 07h
  2489 000067D4 4552524F523A204B65-     	db 'ERROR: Kernel Panic !'
  2489 000067DD 726E656C2050616E69-
  2489 000067E6 632021             
  2490 000067E9 0D0A00                  	db 0Dh, 0Ah, 0
  2491                                  etc_init_err_msg:
  2492 000067EC 0D0A                    	db 0Dh, 0Ah
  2493 000067EE 07                      	db 07h
  2494 000067EF 4552524F523A202F65-     	db 'ERROR: /etc/init !?'
  2494 000067F8 74632F696E69742021-
  2494 00006801 3F                 
  2495 00006802 0D0A00                  	db 0Dh, 0Ah, 0
  2496                                  
  2497                                  ; 10/05/2015
  2498                                  badsys_msg:
  2499 00006805 0D0A                    	db 0Dh, 0Ah
  2500 00006807 07                      	db 07h
  2501 00006808 496E76616C69642053-     	db 'Invalid System Call !'
  2501 00006811 797374656D2043616C-
  2501 0000681A 6C2021             
  2502 0000681D 0D0A                    	db 0Dh, 0Ah
  2503 0000681F 4541583A20              	db 'EAX: '
  2504                                  bsys_msg_eax:
  2505 00006824 303030303030303068      	db '00000000h'
  2506 0000682D 0D0A                    	db 0Dh, 0Ah
  2507 0000682F 4549503A20              	db 'EIP: '
  2508                                  bsys_msg_eip:
  2509 00006834 303030303030303068      	db '00000000h' 
  2510 0000683D 0D0A00                  	db 0Dh, 0Ah, 0
  2511                                  
  2512                                  BSYS_M_SIZE equ $ - badsys_msg
  2513                                  
  2514                                  
  2515                                  align 2
  2516                                  
  2517                                  ; EPOCH Variables
  2518                                  ; 13/04/2015 - Retro UNIX 386 v1 Beginning
  2519                                  ; 09/04/2013 epoch variables
  2520                                  ; Retro UNIX 8086 v1 Prototype: UNIXCOPY.ASM, 10/03/2013
  2521                                  ;
  2522 00006840 B207                    year: 	dw 1970
  2523 00006842 0100                    month: 	dw 1
  2524 00006844 0100                    day: 	dw 1
  2525 00006846 0000                    hour: 	dw 0
  2526 00006848 0000                    minute: dw 0
  2527 0000684A 0000                    second: dw 0
  2528                                  
  2529                                  DMonth:
  2530 0000684C 0000                    	dw 0
  2531 0000684E 1F00                    	dw 31
  2532 00006850 3B00                    	dw 59
  2533 00006852 5A00                    	dw 90
  2534 00006854 7800                    	dw 120
  2535 00006856 9700                    	dw 151
  2536 00006858 B500                    	dw 181
  2537 0000685A D400                    	dw 212
  2538 0000685C F300                    	dw 243
  2539 0000685E 1101                    	dw 273
  2540 00006860 3001                    	dw 304
  2541 00006862 4E01                    	dw 334
  2542                                  
  2543                                  ; 02/01/2022 (Retro UNIX 386 v1.1, Runix Kernel v0.2.1.2)
  2544                                  ; 04/11/2014 (Retro UNIX 386 v1)
  2545 00006864 0000                    mem_1m_1k:   dw 0  ; Number of contiguous KB between
  2546                                  		   ;   1 and 16 MB, max. 3C00h = 15 MB.
  2547 00006866 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2548 00006868 0000                    mem_16m_64k: dw 0  ; Number of contiguous 64 KB blocks
  2549                                  		   ;   between 16 MB and 4 GB.
  2550 0000686A 0000                    	     dw 0  ; 02/01/2022 (Retro UNIX 386 v1.2)
  2551                                  
  2552                                  ; 02/01/2022
  2553                                  KEND:
  2554                                  
  2555 0000686C 90<rep 4h>              align 16
  2556                                  
  2557                                  bss_start:
  2558                                  
  2559                                  ABSOLUTE bss_start
  2560                                  
  2561                                  	; 11/03/2015
  2562                                  	; Interrupt Descriptor Table (20/08/2014)
  2563                                  idt:
  2564 00006870 <res 200h>              	resb	64*8 ; INT 0 to INT 3Fh
  2565                                  idt_end:
  2566                                  
  2567                                  ;alignb 4
  2568                                  
  2569                                  task_state_segment:
  2570                                  	; 24/03/2015
  2571 00006A70 ????                    tss.link:   resw 1
  2572 00006A72 ????                    	    resw 1
  2573                                  ; tss offset 4	
  2574 00006A74 ????????                tss.esp0:   resd 1
  2575 00006A78 ????                    tss.ss0:    resw 1
  2576 00006A7A ????                    	    resw 1	
  2577 00006A7C ????????                tss.esp1:   resd 1
  2578 00006A80 ????                    tss.ss1:    resw 1
  2579 00006A82 ????                    	    resw 1 	
  2580 00006A84 ????????                tss.esp2:   resd 1
  2581 00006A88 ????                    tss.ss2:    resw 1
  2582 00006A8A ????                    	    resw 1
  2583                                  ; tss offset 28
  2584 00006A8C ????????                tss.CR3:    resd 1
  2585 00006A90 ????????                tss.eip:    resd 1
  2586 00006A94 ????????                tss.eflags: resd 1
  2587                                  ; tss offset 40
  2588 00006A98 ????????                tss.eax:    resd 1		 		
  2589 00006A9C ????????                tss.ecx:    resd 1
  2590 00006AA0 ????????                tss.edx:    resd 1
  2591 00006AA4 ????????                tss.ebx:    resd 1
  2592 00006AA8 ????????                tss.esp:    resd 1
  2593 00006AAC ????????                tss.ebp:    resd 1
  2594 00006AB0 ????????                tss.esi:    resd 1
  2595 00006AB4 ????????                tss.edi:    resd 1
  2596                                  ; tss offset 72
  2597 00006AB8 ????                    tss.ES:     resw 1
  2598 00006ABA ????                    	    resw 1	
  2599 00006ABC ????                    tss.CS:	    resw 1
  2600 00006ABE ????                    	    resw 1
  2601 00006AC0 ????                    tss.SS:	    resw 1
  2602 00006AC2 ????                    	    resw 1
  2603 00006AC4 ????                    tss.DS:	    resw 1
  2604 00006AC6 ????                    	    resw 1
  2605 00006AC8 ????                    tss.FS:	    resw 1
  2606 00006ACA ????                    	    resw 1
  2607 00006ACC ????                    tss.GS:	    resw 1
  2608 00006ACE ????                    	    resw 1		
  2609 00006AD0 ????                    tss.LDTR:   resw 1
  2610 00006AD2 ????                    	    resw 1
  2611                                  ; tss offset 100		
  2612 00006AD4 ????                    	    resw 1		
  2613 00006AD6 ????                    tss.IOPB:   resw 1
  2614                                  ; tss offset 104 
  2615                                  tss_end:
  2616                                  
  2617 00006AD8 ????????                k_page_dir:  resd 1 ; Kernel's (System) Page Directory address
  2618                                  		  ;   (Physical address = Virtual address)	 	
  2619 00006ADC ????????                memory_size: resd 1 ; memory size in pages
  2620 00006AE0 ????????                free_pages:  resd 1 ; number of free pages		
  2621 00006AE4 ????????                next_page:   resd 1 ; offset value in M.A.T. for
  2622                                  		  ;   first free page search
  2623 00006AE8 ????????                last_page:   resd 1 ; offset value in M.A.T. which
  2624                                  		  ;   next free page search will be
  2625                                  		  ; stopped after it. (end of M.A.T.)
  2626 00006AEC ????????                first_page:  resd 1 ;   offset value in M.A.T. which
  2627                                  		  ; first free page search
  2628                                  		  ;   will be started on it. (for user)
  2629 00006AF0 ????????                mat_size:    resd 1 ; Memory Allocation Table size in pages		
  2630                                  
  2631                                  ;;;
  2632                                  ; 02/09/2014 (Retro UNIX 386 v1)
  2633                                  ; 04/12/2013 (Retro UNIX 8086 v1)
  2634 00006AF4 ????                    CRT_START:   resw 1 	  ; starting address in regen buffer
  2635                                  			  ; NOTE: active page only
  2636 00006AF6 <res 10h>               cursor_posn: resw 8 	  ; cursor positions for video pages
  2637                                  active_page: 
  2638 00006B06 ??                      ptty: 	     resb 1 	  ; current tty
  2639                                  ; 01/07/2015
  2640 00006B07 ??                      ccolor:	     resb 1	  ; current color attributes ('sysmsg')	
  2641                                  ; 26/10/2015
  2642                                  ; 07/09/2014
  2643 00006B08 <res 14h>               ttychr:      resw ntty+2  ; Character buffer (multiscreen)
  2644                                  
  2645                                  ; 21/08/2014
  2646 00006B1C ????????                tcount:	     resd 1
  2647                                  
  2648                                  ; 18/05/2015 (03/06/2013 - Retro UNIX 8086 v1 feature only!)
  2649 00006B20 ????????                p_time:      resd 1     ; present time (for systime & sysmdate)
  2650                                  
  2651                                  ; 18/05/2015 (16/08/2013 - Retro UNIX 8086 v1 feature only !)
  2652                                  ; (open mode locks for pseudo TTYs)
  2653                                  ; [ major tty locks (return error in any conflicts) ]
  2654 00006B24 <res 14h>               ttyl:        resw ntty+2 ; opening locks for TTYs.
  2655                                  
  2656                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2657                                  ; 22/09/2013 (Retro UNIX 8086 v1)
  2658 00006B38 <res Ah>                wlist:       resb ntty+2 ; wait channel list (0 to 9 for TTYs)
  2659                                  ; 15/04/2015 (Retro UNIX 386 v1)
  2660                                  ;; 12/07/2014 -> sp_init set comm. parameters as 0E3h
  2661                                  ;; 0 means serial port is not available 
  2662                                  ;;comprm: ; 25/06/2014
  2663 00006B42 ??                      com1p:       resb 1  ;;0E3h
  2664 00006B43 ??                      com2p:       resb 1  ;;0E3h
  2665                                  
  2666                                  ; 17/11/2015
  2667                                  ; request for response (from the terminal)	
  2668 00006B44 ????                    req_resp:     resw 1 			
  2669                                  ; 07/11/2015
  2670 00006B46 ??                      ccomport:    resb 1 ; current COM (serial) port
  2671                                  		    ; (0= COM1, 1= COM2)
  2672                                  ; 09/11/2015
  2673 00006B47 ??                      comqr:	     resb 1 ; 'query or response' sign (u9.s, 'sndc')
  2674                                  ; 07/11/2015
  2675 00006B48 ????                    rchar:	     resw 1 ; last received char for COM 1 and COM 2		
  2676 00006B4A ????                    schar:	     resw 1 ; last sent char for COM 1 and COM 2
  2677                                  
  2678                                  ; 23/10/2015
  2679                                  ; SERIAL PORTS - COMMUNICATION MODES
  2680                                  ; (Retro UNIX 386 v1 feature only!)
  2681                                  ; 0 - command mode (default/initial mode)
  2682                                  ; 1 - terminal mode (Retro UNIX 386 v1 terminal, ascii chars)
  2683                                  ;;; communication modes for futre versions:  
  2684                                  ; // 2 - keyboard mode (ascii+scancode input)
  2685                                  ; // 3 - mouse mode
  2686                                  ; // 4 - device control (output) mode
  2687                                  ; VALID COMMANDS for current version:
  2688                                  ; 	'LOGIN'
  2689                                  ;  Login request: db 0FFh, 'LOGIN', 0 
  2690                                  ;	 ("Retro UNIX 386 v1 terminal requests login")
  2691                                  ;  Login response: db 0FFh, 'login', 0
  2692                                  ;	 ("login request accepted, wait for login prompt") 
  2693                                  ; When a login requests is received and acknowledged (by
  2694                                  ; serial port interrupt handler (communication procedure),
  2695                                  ; Retro UNIX 386 v1 operating system will start terminal mode
  2696                                  ; (login procedure) by changing comm. mode to 1 (terminal mode)
  2697                                  ; and then running 'etc/getty' for tty8 (COM1) or tty9 (COM2)
  2698                                  ; 
  2699                                  ; 'sys connect' system call is used to change communication mode
  2700                                  ; except 'LOGIN' command which is used to start terminal mode
  2701                                  ; by using (COM port) terminal.
  2702                                  
  2703                                  ;com1own:     resb 1 ; COM1 owner (u.uno)
  2704                                  ;com2own:     resb 1 ; COM2 owner (u.uno)
  2705                                  ;com1mode:    resb 1 ; communication mode for COM1
  2706                                  ;com1com:     resb 1 ; communication command for COM1
  2707                                  ;com2mode:    resb 1 ; communication mode for COM1
  2708                                  ;com2com      resb 1 ; communication command for COM1
  2709                                  ;com1cbufp:   resb 8 ; COM1 command buffer char pointer	
  2710                                  ;com2cbufp:   resb 8 ; COM2 command buffer char pointer	
  2711                                  ;com1cbuf:    resb 8 ; COM2 command buffer
  2712                                  ;com2cbuf:    resb 8 ; COM2 command buffer
  2713                                  
  2714                                  ; 22/08/2014 (RTC)
  2715                                  ; (Packed BCD)
  2716 00006B4C ??                      time_seconds: resb 1
  2717 00006B4D ??                      time_minutes: resb 1
  2718 00006B4E ??                      time_hours:   resb 1
  2719 00006B4F ??                      date_wday:    resb 1
  2720 00006B50 ??                      date_day:     resb 1
  2721 00006B51 ??                      date_month:   resb 1			
  2722 00006B52 ??                      date_year:    resb 1
  2723 00006B53 ??                      date_century: resb 1
  2724                                  
  2725                                  %include 'diskbss.inc'	; UNINITIALIZED DISK (BIOS) DATA
  2726                              <1> ; Retro UNIX 386 v1 Kernel - DISKBSS.INC
  2727                              <1> ; Last Modification: 10/07/2015
  2728                              <1> ;	(Unnitialized Disk Parameters Data section for 'DISKIO.INC') 
  2729                              <1> ;
  2730                              <1> ; *****************************************************************************
  2731                              <1> 
  2732                              <1> alignb 2
  2733                              <1> 
  2734                              <1> ;----------------------------------------
  2735                              <1> ;	TIMER DATA AREA 		:
  2736                              <1> ;----------------------------------------
  2737                              <1> 
  2738                              <1> TIMER_LH:	; 16/02/205
  2739 00006B54 ????                <1> TIMER_LOW:      resw	1               ; LOW WORD OF TIMER COUNT
  2740 00006B56 ????                <1> TIMER_HIGH:     resw	1               ; HIGH WORD OF TIMER COUNT
  2741 00006B58 ??                  <1> TIMER_OFL:      resb 	1               ; TIMER HAS ROLLED OVER SINCE LAST READ
  2742                              <1> 
  2743                              <1> ;----------------------------------------
  2744                              <1> ;	DISKETTE DATA AREAS		:
  2745                              <1> ;----------------------------------------
  2746                              <1> 
  2747 00006B59 ??                  <1> SEEK_STATUS:	resb	1
  2748 00006B5A ??                  <1> MOTOR_STATUS:	resb	1
  2749 00006B5B ??                  <1> MOTOR_COUNT:	resb	1
  2750 00006B5C ??                  <1> DSKETTE_STATUS:	resb	1
  2751 00006B5D ??????????????      <1> NEC_STATUS:	resb	7
  2752                              <1> 
  2753                              <1> ;----------------------------------------
  2754                              <1> ;	ADDITIONAL MEDIA DATA		:
  2755                              <1> ;----------------------------------------
  2756                              <1> 
  2757 00006B64 ??                  <1> LASTRATE:	resb 	1
  2758 00006B65 ??                  <1> HF_STATUS:	resb 	1
  2759 00006B66 ??                  <1> HF_ERROR:	resb 	1
  2760 00006B67 ??                  <1> HF_INT_FLAG:	resb 	1
  2761 00006B68 ??                  <1> HF_CNTRL:	resb 	1
  2762 00006B69 ????????            <1> DSK_STATE:	resb 	4
  2763 00006B6D ????                <1> DSK_TRK:	resb 	2
  2764                              <1> 
  2765                              <1> ;----------------------------------------
  2766                              <1> ;	FIXED DISK DATA AREAS		:
  2767                              <1> ;----------------------------------------
  2768                              <1> 
  2769 00006B6F ??                  <1> DISK_STATUS1:	resb 	1		; FIXED DISK STATUS
  2770 00006B70 ??                  <1> HF_NUM:		resb 	1		; COUNT OF FIXED DISK DRIVES
  2771 00006B71 ??                  <1> CONTROL_BYTE:	resb 	1		; HEAD CONTROL BYTE
  2772                              <1> ;@PORT_OFF	resb	1		; RESERVED (PORT OFFSET)
  2773                              <1> ;port1_off	resb	1		; Hard disk controller 1 - port offset
  2774                              <1> ;port2_off	resb	1		; Hard idsk controller 2 - port offset
  2775                              <1> 
  2776 00006B72 ????                <1> alignb 4
  2777                              <1> 
  2778                              <1> ;HF_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2779                              <1> ;HF1_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2780                              <1> HF_TBL_VEC: ; 22/12/2014	
  2781 00006B74 ????????            <1> HDPM_TBL_VEC:	resd	1 		; Primary master disk param. tbl. pointer
  2782 00006B78 ????????            <1> HDPS_TBL_VEC:	resd	1		; Primary slave disk param. tbl. pointer
  2783 00006B7C ????????            <1> HDSM_TBL_VEC:	resd	1 		; Secondary master disk param. tbl. pointer
  2784 00006B80 ????????            <1> HDSS_TBL_VEC:	resd	1		; Secondary slave disk param. tbl. pointer
  2785                              <1> 
  2786                              <1> ; 03/01/2015
  2787 00006B84 ??                  <1> LBAMode:     	resb	1
  2788                              <1> 
  2789                              <1> ; *****************************************************************************
  2726                                  
  2727                                  ;;; Real Mode Data (10/07/2015 - BSS)
  2728                                  
  2729                                  ;alignb 2
  2730                                  
  2731                                  ; 02/01/2022
  2732                                  ;%include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2733                                  
  2734                                  ; 24/12/2021
  2735                                  ; (memory page swap parameters are disabled as temporary)
  2736                                  ;
  2737                                  ;; Memory (swap) Data (11/03/2015)
  2738                                  ; 09/03/2015
  2739                                  ;swpq_count: resw 1 ; count of pages on the swap que
  2740                                  ;swp_drv:    resd 1 ; logical drive description table address of the swap drive/disk
  2741                                  ;swpd_size:  resd 1 ; size of swap drive/disk (volume) in sectors (512 bytes).	
  2742                                  ;swpd_free:  resd 1 ; free page blocks (4096 bytes) on swap disk/drive (logical)
  2743                                  ;swpd_next:  resd 1 ; next free page block
  2744                                  ;swpd_last:  resd 1 ; last swap page block	
  2745                                  	
  2746 00006B85 ??????                  alignb 4
  2747                                  
  2748                                  ; 10/07/2015
  2749                                  ; 28/08/2014
  2750 00006B88 ????????                error_code:	resd 1
  2751                                  ; 29/08/2014
  2752 00006B8C ????????                FaultOffset: 	resd 1
  2753                                  ; 21/09/2015
  2754 00006B90 ????????                PF_Count:	resd 1	; total page fault count
  2755                                  		       	; (for debugging - page fault analyze)
  2756                                  		 	; 'page _fault_handler' (memory.inc)
  2757                                  			; 'sysgeterr' (u9.s)
  2758                                  ; 26/02/2022
  2759 00006B94 ????????                rtc_ticks:	resd 1  ; (temporary! this rtc counter value may be used 
  2760                                  			;  for a system call in next retro unix 386 version)
  2761                                  			; -2 ticks per second-
  2762                                  ;; 21/08/2015
  2763                                  ;;buffer: resb (nbuf*520) ;; sysdefs.inc, ux.s
  2764                                  
  2765                                  ; 02/01/2022
  2766                                  %include 'ux.s' ; 12/04/2015 (unix system/user/process data)
  2767                              <1> ; Retro UNIX 386 v1 Kernel (v0.2.1.2) - SYSX.INC (ux.s)
  2768                              <1> ; Last Modification: 26/02/2022
  2769                              <1> ; ----------------------------------------------------------------------------
  2770                              <1> ; Retro UNIX 386 v1 Kernel - ux.s
  2771                              <1> ; Last Modification: 04/12/2015
  2772                              <1> ;
  2773                              <1> ; ///////// RETRO UNIX 386 V1 SYSTEM DEFINITIONS ///////////////
  2774                              <1> ; (Modified from 
  2775                              <1> ;	Retro UNIX 8086 v1 system definitions in 'UNIX.ASM', 01/09/2014)
  2776                              <1> ; ((UNIX.ASM (RETRO UNIX 8086 V1 Kernel), 11/03/2013 - 01/09/2014))
  2777                              <1> ; ----------------------------------------------------------------------------
  2778                              <1> ; Derived from UNIX Operating System (v1.0 for PDP-11) 
  2779                              <1> ; (Original) Source Code by Ken Thompson (1971-1972)
  2780                              <1> ; <Bell Laboratories (17/3/1972)>
  2781                              <1> ; <Preliminary Release of UNIX Implementation Document>
  2782                              <1> ; (Section E10 (17/3/1972) - ux.s)
  2783                              <1> ; ****************************************************************************
  2784                              <1> 
  2785                              <1> alignb 2
  2786                              <1> 
  2787                              <1> inode:
  2788                              <1> 	; 11/03/2013. 
  2789                              <1> 	;Derived from UNIX v1 source code 'inode' structure (ux).
  2790                              <1> 	;i.
  2791                              <1> 
  2792 00006B98 ????                <1> 	i.flgs:	 resw 1
  2793 00006B9A ??                  <1> 	i.nlks:	 resb 1
  2794 00006B9B ??                  <1> 	i.uid:	 resb 1
  2795 00006B9C ????                <1>         i.size:  resw 1 ; size
  2796 00006B9E <res 10h>           <1> 	i.dskp:	 resw 8 ; 16 bytes
  2797 00006BAE ????????            <1> 	i.ctim:	 resd 1
  2798 00006BB2 ????????            <1> 	i.mtim:	 resd 1
  2799 00006BB6 ????                <1> 	i.rsvd:  resw 1 ; Reserved (ZERO/Undefined word for UNIX v1.)
  2800                              <1> 
  2801                              <1> I_SIZE	equ $ - inode 
  2802                              <1> 
  2803                              <1> process:
  2804                              <1> 	; 26/02/2022
  2805                              <1> 	; 12/01/2022 (Retro UNIX 386 v1.1) 
  2806                              <1> 	; 06/05/2015
  2807                              <1> 	; 11/03/2013 - 05/02/2014
  2808                              <1> 	;Derived from UNIX v1 source code 'proc' structure (ux).
  2809                              <1> 	;p.
  2810                              <1> 	
  2811 00006BB8 <res 20h>           <1>         p.pid:   resw nproc
  2812 00006BD8 <res 20h>           <1>         p.ppid:  resw nproc
  2813                              <1> 	;p.break: resw nproc ; 12/01/2022 (p.break is not used)
  2814 00006BF8 <res 10h>           <1>         p.ttyc:  resb nproc ; console tty in Retro UNIX 8086 v1.
  2815                              <1> 	; 26/02/2022 (p.waitc is not used)
  2816                              <1> 	;p.waitc: resb nproc ; waiting channel in Retro UNIX 8086 v1.
  2817 00006C08 <res 10h>           <1> 	p.link:	 resb nproc
  2818 00006C18 <res 10h>           <1> 	p.stat:	 resb nproc
  2819                              <1> 
  2820                              <1> 	; 06/05/2015 (Retro UNIX 386 v1 fetaure only !) 
  2821 00006C28 <res 40h>           <1> 	p.upage: resd nproc ; Physical address of the process's
  2822                              <1> 			    ; 'user' structure	
  2823                              <1> 
  2824                              <1> P_SIZE	equ $ - process
  2825                              <1> 
  2826                              <1> ; fsp table (original UNIX v1)
  2827                              <1> ;
  2828                              <1> ;Entry
  2829                              <1> ;          15                                      0
  2830                              <1> ;  1     |---|---------------------------------------|
  2831                              <1> ;        |r/w|       i-number of open file           |
  2832                              <1> ;        |---|---------------------------------------| 
  2833                              <1> ;        |               device number               |
  2834                              <1> ;        |-------------------------------------------|
  2835                              <1> ;    (*) | offset pointer, i.e., r/w pointer to file |
  2836                              <1> ;        |-------------------------------------------| 
  2837                              <1> ;        |  flag that says    | number of processes  |
  2838                              <1> ;        |   file deleted     | that have file open  |
  2839                              <1> ;        |-------------------------------------------| 
  2840                              <1> ;  2     |                                           |
  2841                              <1> ;        |-------------------------------------------| 
  2842                              <1> ;        |                                           |
  2843                              <1> ;        |-------------------------------------------|
  2844                              <1> ;        |                                           |
  2845                              <1> ;        |-------------------------------------------|
  2846                              <1> ;        |                                           |
  2847                              <1> ;        |-------------------------------------------| 
  2848                              <1> ;  3     |                                           | 
  2849                              <1> ;        |                                           |  
  2850                              <1> ;
  2851                              <1> ; (*) Retro UNIX 386 v1 modification: 32 bit offset pointer 
  2852                              <1> 
  2853                              <1> ; 15/04/2015
  2854 00006C68 <res 1F4h>          <1> fsp:	 resb nfiles*10 ; 11/05/2015 (8 -> 10)
  2855 00006E5C <res 20h>           <1> bufp:	 resd (nbuf+2) ; will be initialized 
  2856 00006E7C ????                <1> ii:	 resw 1
  2857                              <1> ;idev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2858                              <1> ;cdev:	 resw 1 ; device number is 1 byte in Retro UNIX 8086 v1 !
  2859                              <1> ; 11/01/2022
  2860 00006E7E ??                  <1> idev:	 resb 1
  2861 00006E7F ??                  <1> cdev:	 resb 1
  2862                              <1> ; 18/05/2015
  2863                              <1> ; 26/04/2013 device/drive parameters (Retro UNIX 8086 v1 feature only!)
  2864                              <1> ; 'UNIX' device numbers (as in 'cdev' and 'u.cdrv')
  2865                              <1> ;	0 -> root device (which has Retro UNIX 8086 v1 file system)
  2866                              <1> ; 	1 -> mounted device (which has Retro UNIX 8086 v1 file system)
  2867                              <1> ; 'Retro UNIX 8086 v1' device numbers: (for disk I/O procedures)
  2868                              <1> ;	0 -> fd0 (physical drive, floppy disk 1), physical drive number = 0
  2869                              <1> ;	1 -> fd1 (physical drive, floppy disk 2), physical drive number = 1
  2870                              <1> ;	2 -> hd0 (physical drive, hard disk 1), physical drive number = 80h
  2871                              <1> ;	3 -> hd1 (physical drive, hard disk 2), physical drive number = 81h
  2872                              <1> ;	4 -> hd2 (physical drive, hard disk 3), physical drive number = 82h
  2873                              <1> ;	5 -> hd3 (physical drive, hard disk 4), physical drive number = 83h
  2874 00006E80 ??                  <1> rdev:	 resb 1 ; root device number ; Retro UNIX 8086 v1 feature only!
  2875                              <1> 	        ; as above, for physical drives numbers in following table
  2876 00006E81 ??                  <1> mdev:	 resb 1 ; mounted device number ; Retro UNIX 8086 v1 feature only!
  2877                              <1> ; 15/04/2015
  2878 00006E82 ??                  <1> active:	 resb 1 
  2879 00006E83 ??                  <1> 	 resb 1 ; 09/06/2015
  2880 00006E84 ????                <1> mnti:	 resw 1
  2881 00006E86 ????                <1> mpid:	 resw 1
  2882 00006E88 ????                <1> rootdir: resw 1
  2883                              <1> ; 14/02/2014
  2884                              <1> ; Major Modification: Retro UNIX 8086 v1 feature only!
  2885                              <1> ;		      Single level run queue
  2886                              <1> ;		      (in order to solve sleep/wakeup lock)
  2887 00006E8A ????                <1> runq:	 resw 1
  2888 00006E8C ??                  <1> imod:	 resb 1
  2889 00006E8D ??                  <1> smod:	 resb 1
  2890 00006E8E ??                  <1> mmod:	 resb 1
  2891 00006E8F ??                  <1> sysflg:	 resb 1
  2892                              <1> 
  2893                              <1> alignb 4
  2894                              <1> 
  2895                              <1> user:
  2896                              <1> 	; 09/01/2022 (Retro UNIX 386 v1.1, Kernel v0.2.1.2)
  2897                              <1> 	; 04/12/2015 
  2898                              <1> 	; 18/10/2015
  2899                              <1> 	; 12/10/2015
  2900                              <1> 	; 21/09/2015
  2901                              <1> 	; 24/07/2015
  2902                              <1> 	; 16/06/2015
  2903                              <1> 	; 09/06/2015
  2904                              <1> 	; 11/05/2015
  2905                              <1> 	; 16/04/2015 (Retro UNIX 386 v1 - 32 bit modifications)
  2906                              <1> 	; 10/10/2013
  2907                              <1> 	; 11/03/2013. 
  2908                              <1> 	;Derived from UNIX v1 source code 'user' structure (ux).
  2909                              <1> 	;u.
  2910                              <1> 
  2911 00006E90 ????????            <1> 	u.sp:	  resd 1 ; esp (kernel stack at the beginning of 'sysent')
  2912 00006E94 ????????            <1> 	u.usp:	  resd 1 ; esp (kernel stack points to user's registers)
  2913 00006E98 ????????            <1> 	u.r0:	  resd 1 ; eax
  2914 00006E9C ????                <1> 	u.cdir:	  resw 1
  2915 00006E9E <res Ah>            <1> 	u.fp:	  resb 10
  2916 00006EA8 ????????            <1> 	u.fofp:	  resd 1
  2917 00006EAC ????????            <1> 	u.dirp:	  resd 1
  2918 00006EB0 ????????            <1> 	u.namep:  resd 1
  2919 00006EB4 ????????            <1> 	u.off:	  resd 1
  2920 00006EB8 ????????            <1> 	u.base:	  resd 1
  2921 00006EBC ????????            <1> 	u.count:  resd 1
  2922 00006EC0 ????????            <1> 	u.nread:  resd 1
  2923 00006EC4 ????????            <1> 	u.break:  resd 1 ; break
  2924 00006EC8 ????                <1> 	u.ttyp:	  resw 1 
  2925 00006ECA <res 10h>           <1> 	u.dirbuf: resb 16 ; 04/12/2015 (10 -> 16) 
  2926                              <1> 	;u.pri:	  resw 1 ; 14/02/2014
  2927 00006EDA ??                  <1> 	u.quant:  resb 1 ; Retro UNIX 8086 v1 Feature only ! (uquant)
  2928 00006EDB ??                  <1> 	u.pri:	  resb 1 ; 
  2929 00006EDC ????                <1> 	u.intr:	  resw 1
  2930 00006EDE ????                <1> 	u.quit:	  resw 1
  2931                              <1> 	;u.emt:	  resw 1 ; 10/10/2013
  2932 00006EE0 ????                <1> 	u.ilgins: resw 1
  2933                              <1> 	;u.cdrv:  resw 1 ; cdev
  2934 00006EE2 ??                  <1> 	u.cdrv:   resb 1 ; 09/01/2022
  2935 00006EE3 ??                  <1> 		  resb 1 ; 09/01/2022 (dword alignment)
  2936 00006EE4 ??                  <1> 	u.uid:	  resb 1 ; uid
  2937 00006EE5 ??                  <1> 	u.ruid:	  resb 1
  2938 00006EE6 ??                  <1> 	u.bsys:	  resb 1
  2939 00006EE7 ??                  <1> 	u.uno:	  resb 1
  2940 00006EE8 ????????            <1>         u.upage:  resd 1 ; 16/04/2015 - Retro Unix 386 v1 feature only !
  2941                              <1> 	; tty number (rtty, rcvt, wtty)
  2942 00006EEC ??                  <1> 	u.ttyn:	  resb 1 ; 28/07/2013 - Retro Unix 8086 v1 feature only !
  2943                              <1> 	; last error number
  2944 00006EED ????????            <1> 	u.error:  resd 1 ; 28/07/2013 - 09/03/2015 
  2945                              <1> 		        ; Retro UNIX 8086/386 v1 feature only!
  2946 00006EF1 ????????            <1> 	u.pgdir:  resd 1 ; 09/03/2015 (page dir addr of process)
  2947 00006EF5 ????????            <1> 	u.ppgdir: resd 1 ; 06/05/2015 (page dir addr of the parent process)
  2948 00006EF9 ????????            <1> 	u.pbase:  resd 1 ; 20/05/2015 (physical base/transfer address)
  2949 00006EFD ????                <1> 	u.pcount: resw 1 ; 20/05/2015 (byte -transfer- count for page)
  2950                              <1> 	;u.pncount: resw 1 
  2951                              <1> 		; 16/06/2015 (byte -transfer- count for page, 'namei', 'mkdir')
  2952                              <1> 	;u.pnbase:  resd 1 
  2953                              <1> 		; 16/06/2015 (physical base/transfer address, 'namei', 'mkdir')
  2954                              <1> 			 ; 09/06/2015
  2955 00006EFF ??                  <1> 	u.kcall:  resb 1 ; The caller is 'namei' (dskr) or 'mkdir' (dskw) sign		
  2956 00006F00 ??                  <1> 	u.brwdev: resb 1 ; Block device number for direct I/O (bread & bwrite)
  2957                              <1> 			 ; 24/07/2015 - 24/06/2015
  2958                              <1> 	;u.args:  resd 1 ; arguments list (line) offset from start of [u.upage]
  2959                              <1> 			 ; (arg list/line is from offset [u.args] to 4096 in [u.upage])
  2960                              <1> 			 ; ([u.args] points to argument count -argc- address offset)
  2961                              <1>  			 ; 24/06/2015	  	
  2962                              <1> 	;u.core:  resd 1 ; physical start address of user's memory space (for sys exec)
  2963                              <1> 	;u.ecore: resd 1 ; physical end address of user's memory space (for sys exec)
  2964                              <1> 			 ; 21/09/2015 (debugging - page fault analyze)
  2965 00006F01 ????????            <1> 	u.pfcount: resd 1 ; page fault count for (this) process (for sys geterr)
  2966                              <1> 
  2967 00006F05 ??????              <1> alignb 4
  2968                              <1> 
  2969                              <1> U_SIZE	equ $ - user
  2970                              <1> 
  2971                              <1> ; 18/10/2015 - Retro UNIX 386 v1 (local variables for 'namei' and 'sysexec')
  2972 00006F08 ????????            <1> pcore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2973 00006F0C ????????            <1> ecore:  resd 1 ; physical start address of user's memory space (for sys exec)
  2974 00006F10 ????????            <1> nbase:	resd 1	; physical base address for 'namei' & 'sysexec'
  2975 00006F14 ????                <1> ncount: resw 1	; remain byte count in page for 'namei' & 'sysexec'
  2976                              <1> ;argc:	resw 1	; argument count for 'sysexec'
  2977 00006F16 ??                  <1> argc:	resb 1	; 12/01/2022 - Retro UNIX 386 v1.1 (Kernel v0.2.1.2)
  2978 00006F17 ??                  <1> 	resb 1 
  2979 00006F18 ????????            <1> argv:	resd 1	; argument list (recent) address for 'sysexec'
  2980                              <1> 
  2981                              <1> ; 03/06/2015 - Retro UNIX 386 v1 Beginning
  2982                              <1> ; 07/04/2013 - 31/07/2013 - Retro UNIX 8086 v1
  2983 00006F1C ??                  <1> rw: 	 resb 1 ;; Read/Write sign (iget)
  2984 00006F1D ??                  <1> rwdsk:	 resb 1 ;; Read/Write function number (diskio) - 16/06/2015
  2985 00006F1E ??                  <1> retry_count: resb 1 ; Disk I/O retry count - 11/06/2015
  2986 00006F1F ??                  <1> 	 resb 1 ;; Reserved (16/06/2015) 
  2987                              <1> 
  2988                              <1> ;alignb 4
  2989                              <1> 
  2990                              <1> ; 22/08/2015
  2991 00006F20 <res C30h>          <1> buffer: resb nbuf * 520
  2992                              <1> 
  2993 00007B50 ????????????????    <1> sb0:	resd 2
  2994                              <1> ;s:
  2995                              <1> ; (root disk) super block buffer
  2996                              <1> systm:
  2997                              <1> 	; 13/11/2015 (Retro UNIX 386 v1)	
  2998                              <1> 	; 11/03/2013. 
  2999                              <1> 	;Derived from UNIX v1 source code 'systm' structure (ux).
  3000                              <1> 	;s.
  3001                              <1> 
  3002 00007B58 ????                <1> 	resw 1
  3003 00007B5A <res 168h>          <1> 	resb 360 ; 2880 sectors ; original UNIX v1 value: 128
  3004 00007CC2 ????                <1> 	resw 1
  3005 00007CC4 <res 20h>           <1> 	resb 32	 ; 256+40 inodes ; original UNIX v1 value: 64
  3006                              <1> eofitab equ $ - systm ; 11/02/2022 (end of inode table)
  3007 00007CE4 ????????            <1> 	s.time:	 resd 1
  3008 00007CE8 ????????            <1> 	s.syst:	 resd 1
  3009 00007CEC ????????            <1>         s.wait_: resd 1 ; wait
  3010 00007CF0 ????????            <1> 	s.idlet: resd 1
  3011 00007CF4 ????????            <1> 	s.chrgt: resd 1
  3012 00007CF8 ????                <1> 	s.drerr: resw 1
  3013                              <1> 
  3014                              <1> S_SIZE	equ $ - systm
  3015                              <1> 
  3016 00007CFA <res 5Eh>           <1> 	resb 512-S_SIZE ; 03/06/2015	 
  3017                              <1> 
  3018 00007D58 ????????????????    <1> sb1:	resd 2
  3019                              <1> ; (mounted disk) super block buffer
  3020                              <1> mount:	
  3021 00007D60 <res 200h>          <1> 	resb 512  ; 03/06/2015
  3022                              <1> 
  3023                              <1> ;/ ux -- unix
  3024                              <1> ;
  3025                              <1> ;systm:
  3026                              <1> ;
  3027                              <1> ;	.=.+2
  3028                              <1> ;	.=.+128.
  3029                              <1> ;	.=.+2
  3030                              <1> ;	.=.+64.
  3031                              <1> ;	s.time: .=.+4
  3032                              <1> ;	s.syst: .=.+4
  3033                              <1> ;	s.wait: .=.+4
  3034                              <1> ;	s.idlet:.=.+4
  3035                              <1> ;	s.chrgt:.=.+4
  3036                              <1> ;	s.drerr:.=.+2
  3037                              <1> ;inode:
  3038                              <1> ;	i.flgs: .=.+2
  3039                              <1> ;	i.nlks: .=.+1
  3040                              <1> ;	i.uid:  .=.+1
  3041                              <1> ;	i.size: .=.+2
  3042                              <1> ;	i.dskp: .=.+16.
  3043                              <1> ;	i.ctim: .=.+4
  3044                              <1> ;	i.mtim: .=.+4
  3045                              <1> ;	. = inode+32.
  3046                              <1> ;mount:	.=.+1024.
  3047                              <1> ;proc:
  3048                              <1> ;	p.pid:  .=.+[2*nproc]
  3049                              <1> ;	p.dska: .=.+[2*nproc]
  3050                              <1> ;	p.ppid: .=.+[2*nproc]
  3051                              <1> ;	p.break:.=.+[2*nproc]
  3052                              <1> ;	p.link: .=.+nproc
  3053                              <1> ;	p.stat: .=.+nproc
  3054                              <1> ;tty:
  3055                              <1> ;	. = .+[ntty*8.]
  3056                              <1> ;fsp:	.=.+[nfiles*8.]
  3057                              <1> ;bufp:	.=.+[nbuf*2]+6
  3058                              <1> ;sb0:	.=.+8
  3059                              <1> ;sb1:	.=.+8
  3060                              <1> ;swp:	.=.+8
  3061                              <1> ;ii:	.=.+2
  3062                              <1> ;idev:	.=.+2
  3063                              <1> ;cdev:	.=.+2
  3064                              <1> ;deverr: .=.+12.
  3065                              <1> ;active: .=.+2
  3066                              <1> ;rfap:	.=.+2
  3067                              <1> ;rkap:	.=.+2
  3068                              <1> ;tcap:	.=.+2
  3069                              <1> ;tcstate:.=.+2
  3070                              <1> ;tcerrc: .=.+2
  3071                              <1> ;mnti:	.=.+2
  3072                              <1> ;mntd:	.=.+2
  3073                              <1> ;mpid:	.=.+2
  3074                              <1> ;clockp: .=.+2
  3075                              <1> ;rootdir:.=.+2
  3076                              <1> ;toutt:	.=.+16.
  3077                              <1> ;touts: .=.+32.
  3078                              <1> ;runq:	.=.+6
  3079                              <1> ;
  3080                              <1> ;wlist:	.=.+40.
  3081                              <1> ;cc:	.=.+30.
  3082                              <1> ;cf:	.=.+31.
  3083                              <1> ;cl:	.=.+31.
  3084                              <1> ;clist:	.=.+510.
  3085                              <1> ;imod:	.=.+1
  3086                              <1> ;smod:	.=.+1
  3087                              <1> ;mmod:	.=.+1
  3088                              <1> ;uquant: .=.+1
  3089                              <1> ;sysflg: .=.+1
  3090                              <1> ;pptiflg:.=.+1
  3091                              <1> ;ttyoch: .=.+1
  3092                              <1> ; .even
  3093                              <1> ; .=.+100.; sstack:
  3094                              <1> ;buffer: .=.+[ntty*140.]
  3095                              <1> ;	.=.+[nbuf*520.]
  3096                              <1> ;
  3097                              <1> ; . = core-64.
  3098                              <1> ;user:
  3099                              <1> ;	u.sp:    .=.+2
  3100                              <1> ;	u.usp:   .=.+2
  3101                              <1> ;	u.r0:    .=.+2
  3102                              <1> ;	u.cdir:  .=.+2
  3103                              <1> ;	u.fp:    .=.+10.
  3104                              <1> ;	u.fofp:  .=.+2
  3105                              <1> ;	u.dirp:  .=.+2
  3106                              <1> ;	u.namep: .=.+2
  3107                              <1> ;	u.off:   .=.+2
  3108                              <1> ;	u.base:  .=.+2
  3109                              <1> ;	u.count: .=.+2
  3110                              <1> ;	u.nread: .=.+2
  3111                              <1> ;	u.break: .=.+2
  3112                              <1> ;	u.ttyp:  .=.+2
  3113                              <1> ;	u.dirbuf:.=.+10.
  3114                              <1> ;	u.pri:   .=.+2
  3115                              <1> ;	u.intr:  .=.+2
  3116                              <1> ;	u.quit:  .=.+2
  3117                              <1> ;	u.emt:   .=.+2
  3118                              <1> ;	u.ilgins:.=.+2
  3119                              <1> ;	u.cdev:  .=.+2
  3120                              <1> ;	u.uid:   .=.+1
  3121                              <1> ;	u.ruid:  .=.+1
  3122                              <1> ;	u.bsys:  .=.+1
  3123                              <1> ;	u.uno:   .=.+1
  3124                              <1> ;. = core
  2767                                  
  2768                                  ; 27/12/2021
  2769                                  ;buffer: resb (nbuf*520)
  2770                                  
  2771                                  bss_end:
  2772                                  
  2773                                  ; 02/01/2022
  2774                                  BSS_SIZE equ bss_end - bss_start
  2775                                  
  2776                                  ; 27/12/2013
  2777                                  _end:  ; end of kernel code (and read only data, just before bss)
